一、生成器和迭代器
1.列表生成
>>> a [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> a = map(lambda x:x+1, a) >>> a <map object at 0x101d2c630> >>> for i in a:print(i) ... 3 5 7 9 11 或者 >>> a = [i+1 for i in range(10)] >>> a [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
1 data = [1,2,3,4,5,6,7,8] 2 r = [i*2 if i>4 else i for i in data] 3 print(r)
2.创建生成器
生成器作用是不占用空间,使用哪一个调用即可,不使用就不调用。
1 >>> g = (x * x for x in range(10)) 2 >>> g 3 <generator object <genexpr> at 0x1022ef630>
1 >>> g = (x * x for x in range(10)) 2 >>> for n in g: 3 ... print(n) 4 ... 5 0 6 1 7 4 8 9 9 16 10 25 11 36 12 49 13 64 14 81
1 def fib(max): 2 n, a, b = 0, 0, 1 3 while n < max: 4 print(b) 5 a, b = b, a + b 6 n = n + 1 7 return 'done'
1 def fib(num): 2 count = 0 3 a,b = 0,1 4 while count<num: 5 a,b = b,a+b 6 7 count+=1 8 yield a #yield表示返回a 但不会终止 9 print("done....") 10 f = fib(10) 11 for i in f:print(i)
generator和函数的执行流程的区别:函数是顺序执行,遇到return
语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()
的时候执行,遇到yield
语句返回,再次执行时从上次返回的yield
语句处继续执行。
我们基本不会用next()来获取下一个返回值,而是直接使用for
循环来迭代
3.利用生成器实现单线程并发运算
1 def consumer(name): 2 print("%s 准备吃包子啦!"%name) 3 while True: 4 baozi=yield 5 print("包子[%s]来了,被[%s]吃了" %(baozi,name)) 6 7 def producer(name): 8 c=consumer("A") 9 c2=consumer("B") 10 c.__next__() 11 c2.__next__() 12 print("老子开始做包子啦!") 13 for i in range(10): 14 time.sleep(1) 15 print("做了2个包子") 16 c.send(i) 17 c2.send(i) 18 producer("alex")
4.迭代器
可以直接用作for循环的对象统称可迭代对象:Iterable
可以使用isinstance()
判断一个对象是否是Iterable
对象:
可以被next()
函数调用并不断返回下一个值的对象称为迭代器:Iterator
。
总结:
凡是可作用于for
循环的对象都是Iterable
类型;
凡是可作用于next()
函数的对象都是Iterator
类型,它们表示一个惰性计算的序列;
集合数据类型如list
、dict
、str
等是Iterable
但不是Iterator
,不过可以通过iter()
函数获得一个Iterator
对象。
二、装饰器
要求不改变原代码的情况下,遵循开放-封闭原则,对原函数进行包装扩展功能。
核心:1.@+函数 会自动执行@函数,并将被装饰的函数作为参数传递。
2.将@函数的返回值重新赋值给被装饰的函数。
1 user_status = False # 用户登录了就把这个改成True 2 def login(func): # 把要执行的模块从这里传进来 3 def inner(*args, **kwargs): # 再定义一层函数 4 _username = "alex" # 假装这是DB里存的用户信息 5 _password = "abc123" # 假装这是DB里存的用户信息 6 global user_status 7 if user_status == False: 8 username = input("user:") 9 password = input("pasword:") 10 if username == _username and password == _password: 11 print("welcome login....") 12 user_status = True 13 else: 14 print("wrong username or password!") 15 if user_status == True: 16 func(*args, **kwargs) # 看这里看这里,只要验证通过了,就调用相应功能 17 return inner # 用户调用login时,只会返回inner的内存地址,下次再调用时加上()才会执行inner函数 18 def home(): 19 print("---首页----") 20 @login 21 def america(): 22 print("----欧美专区----") 23 def japan(): 24 print("----日韩专区----") 25 # @login 26 def henan(style): 27 print("----河南专区----") 28 home() 29 america() 30 japan() 31 henan("3p")
通过装饰器权限控制的实例
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # Author:Liumj 4 USER_INFO = {} 5 def check_login(func): 6 def inner(*args,**kwargs): 7 if USER_INFO.get('is_login'): 8 ret = func(*args,**kwargs) 9 return ret 10 else: 11 print("请登录") 12 return inner 13 def check_admin(func): 14 def inner(*args,**kwargs): 15 if USER_INFO.get('user_type') == 2: 16 ret = func(*args,**kwargs) 17 return ret 18 else: 19 print("无权查看") 20 return inner 21 @check_admin 22 @check_login 23 def index(): 24 print('Index') 25 @check_login 26 def home(): 27 print('home') 28 29 def login(): 30 user = input('请输入用户名:') 31 if user == 'admin': 32 USER_INFO['is_login'] = True 33 USER_INFO['user_type'] = 2 34 print("超级管理员登陆成功!") 35 else: 36 USER_INFO['is_login'] = True 37 USER_INFO['user_type'] = 1 38 39 40 def main(): 41 while True: 42 inp = input("1,登陆: 2.查看信息: 3.超级管理员 >>>" ) 43 if inp == "1": 44 login() 45 elif inp == "2": 46 home() 47 elif inp == "3": 48 index() 49 main()
三、常用模块
n个 .py 文件组成的代码集合就称为模块。
模块分为:内置模块(标准库)、自定义模块、开源模块
1.OS模块
1 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 2 os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd 3 os.curdir 返回当前目录: ('.') 4 os.pardir 获取当前目录的父目录字符串名:('..') 5 os.makedirs('dirname1/dirname2') 可生成多层递归目录 6 os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 7 os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname 8 os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname 9 os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 10 os.remove() 删除一个文件 11 os.rename("oldname","newname") 重命名文件/目录 12 os.stat('path/filename') 获取文件/目录信息 13 os.sep 输出操作系统特定的路径分隔符,win下为"\",Linux下为"/" 14 os.linesep 输出当前平台使用的行终止符,win下为" ",Linux下为" " 15 os.pathsep 输出用于分割文件路径的字符串 16 os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix' 17 os.system("bash command") 运行shell命令,直接显示 18 os.environ 获取系统环境变量 19 os.path.abspath(path) 返回path规范化的绝对路径 20 os.path.split(path) 将path分割成目录和文件名二元组返回 21 os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素 22 os.path.basename(path) 返回path最后的文件名。如何path以/或结尾,那么就会返回空值。即os.path.split(path)的第二个元素 23 os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False 24 os.path.isabs(path) 如果path是绝对路径,返回True 25 os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False 26 os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False 27 os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 28 os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间 29 os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间
2.sys模块
1 sys.argv 命令行参数List,第一个元素是程序本身路径 2 sys.exit(n) 退出程序,正常退出时exit(0) 3 sys.version 获取Python解释程序的版本信息 4 sys.maxint 最大的Int值 5 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 6 sys.platform 返回操作系统平台名称 7 sys.stdout.write('please:') 8 val = sys.stdin.readline()[:-1] 9
四、序列化和反序列化
json,用于字符串和python数据类型之间的转换
pickle,用于python特有的类型和python的数据类型之间进行转换
Json模块提供了四个功能:dumps、dump、loads、load
pickle模块提供了四个功能:dumps、dump、loads、load
实例用法
1 import json 2 data = { 3 "name":"alex", 4 "age":22, 5 "sex":"M" 6 } 7 f = open("data.txt","w",encoding="utf-8") 8 #f.write(json.dumps(data)) #dumps用法 9 json.dump(data,f) #dump用法 10 f.close() 11 12 13 14 import json 15 f = open("data.txt",encoding="utf-8") 16 #d = json.loads(f.read()) #loads用法 17 d = json.load(f) #load用法 18 print(d,type(d))
四、开发规范
设计好目录结构
优点:
可读性高: 不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等。从而非常快速的了解这个项目。
可维护性高: 定义好组织规则后,维护者就能很明确地知道,新增的哪个文件和代码应该放在什么目录之下。这个好处是,随着时间的推移,代码/配置的规模增加,项目结构不会混乱,仍然能够组织良好。
目录组织方式:
Foo/ |-- bin/ | |-- foo | |-- foo/ | |-- tests/ | | |-- __init__.py | | |-- test_main.py | | | |-- __init__.py | |-- main.py | |-- docs/ | |-- conf.py | |-- abc.rst | |-- setup.py |-- requirements.txt |-- README
简要解释一下:
bin/
: 存放项目的一些可执行文件,当然你可以起名script/
之类的也行。foo/
: 存放项目的所有源代码。(1) 源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。(2) 其子目录tests/
存放单元测试代码; (3) 程序的入口最好命名为main.py
。docs/
: 存放一些文档。setup.py
: 安装、部署、打包的脚本。requirements.txt
: 存放软件依赖的外部Python包列表。README
: 项目说明文件。
readme 目的是能简要描述该项目的信息,让读者快速了解这个项目。
它需要说明以下几个事项:
- 软件定位,软件的基本功能。
- 运行代码的方法: 安装环境、启动命令等。
- 简要的使用说明。
- 代码目录结构说明,更详细点可以说明软件的基本原理。
- 常见问题说明。
我觉得有以上几点是比较好的一个README
。在软件开发初期,由于开发过程中以上内容可能不明确或者发生变化,并不是一定要在一开始就将所有信息都补全。但是在项目完结的时候,是需要撰写这样的一个文档的。