python基础-装饰器,生成器和迭代器
学习内容
1.装饰器
2.生成器
3.迭代器
4.软件目录结构规范
一:装饰器(decorator)
1.装饰器定义:本质就是函数,用来装饰其他函数,即为其他函数添加附加功能。
2.装饰器原则:1)不能修改被装饰函数的源代码2)不能修改被装饰函数的调用方式
3.装饰器的知识储备
1)函数即是变量
2)高阶函数:a,把一个函数名当作实参给别外一个函数(在不修改被装饰函数源代码的情况下实现增加附加功能)
b,返回值中包括函数名(不修改函数调用方式)
3)嵌套函数:用def 在别外的函数中定义的函数
装饰器=高阶函数+嵌套函数
4.装饰器使用:1)被装饰函数不带参数2)被装饰函数带有参数3)装饰多个函数,根据被装饰函数不同,增加不同的装饰功能。
1)实现被装饰函数不带参数代码
三个页面,index不需要登陆,home,bbs页面需要登录
# -*- coding:utf-8 -*- __author__ = 'shisanjun' """ 实现被装饰函数不带参数代码 """ def login(func): #传递函数标识 def wrapper(): #函数嵌套 print("实现登陆") func() #执行函数 return wrapper #返回函数标识 def index(): print("you in the index page") @login #@login=(home=login(home)) def home(): print("you in the home page") @login def bbs(): print("you in the bbs page") index() home() bbs()
2)实现被装饰函数带参数代码
三个页面,index不需要登陆,home,bbs页面需要登录
# -*- coding:utf-8 -*- __author__ = 'shisanjun' """ 实现被装饰函数带参数代码 """ def login(func): #传递函数标识 def wrapper(*args,**kwargs): #函数嵌套,传递被装饰函数的参数 print("实现登陆") func(*args,**kwargs) #执行函数 return wrapper #返回函数标识 def index(name): print("%s in the home page" %name) @login def home(name): print("%s in the home page" %name) @login def bbs(name): print("%s in the home page" %name) index("shisan") home("shisan") bbs("shisan")
2)装饰多个函数,根据被装饰函数不同,增加不同的装饰功能。
三个页面,index不需要登陆,home,bbs页面需要登录
# -*- coding:utf-8 -*-
__author__ = 'shisanjun'
"""
装饰多个函数,根据被装饰函数不同,实现不同的装饰功能
"""
#嵌套三层函数
def login(flag): #传递类型
def out_wrapper(func):#传递函数标识
def wrapper(*args,**kwargs): #函数嵌套,传递被装饰函数的参数
if flag=="home":
print("实现home装饰")
else:
print("实现bbs装饰")
func(*args,**kwargs)
return wrapper
return out_wrapper
def index(name):
print("%s in the home page" %name)
@login(flag="home")
def home(name):
print("%s in the home page" %name)
@login(flag="bbs")
def bbs(name):
print("%s in the home page" %name)
index("shisan")
home("shisan")
bbs("shisan")
二.生成器
列表生成式,例如:[x for i in range(10)]
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费。
生成器(generator):通过一边循环一边生成机制就生成器.
生成器只有在调用时才会生成相应的数据,只记录当前的位置
创建生成器方法 一是:(x for i in range(10))二是:如果一个函数定义中包含yield
关键字,那么这个函数就不再是一个普通函数,而是一个generator
[x for i in range(10)]是列表
(x for i in range(10))是generator
generator保存的是算法,每次调用next(g)
,就计算出g
的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration
的错误
python2中是next() python3中是__next__()
创建了一个generator后,基本上永远不会调用next()
,而是通过for
循环来迭代它,并且不需要关心StopIteration
的错误
生成器示例代码
# -*- coding:utf-8 -*- __author__ = 'shisanjun' l=[x*2 for x in range(10)] #列表生成式 print(l) g=(x*2 for x in range(3)) #创建生成器方式一 print(g) #提示是generator # print(g.__next__()) #访问方式一是通过高用__next方法 # print(g.__next__()) # print(g.__next__()) # print(g.__next__()) #访问抛出异常StopIteration # g=(x*2 for x in range(3)) # for i in g: #通过for访问是没有异常的 # print(i) # #捕获StopIteration方式 while True: try: print(g.__next__()) except StopIteration as e: print("generator except:%s" %e.value) break
通过yeild生成generator
# -*- coding:utf-8 -*- __author__ = 'shisanjun' def fib(max):#斐波拉契数列 n,a,b=0,0,1 while True: yield b a,b=b,a+b #t=(b,a+b) a=t[0],b=t[1] n+=1 if n>max: break return "done" f=fib(10) while True: try: print(f.__next__()) except StopIteration as e: print("generator stop" ,e.value) break
三.迭代器
可以直接用于for循环的对象就迭代对象:Iterable。集合类list,set,dict,str,tuple;generator类生成器和带yield的generator function
可以使用isinstance()判断是对象是不是迭代对象。
可以被next()
函数调用并不断返回下一个值的对象称为迭代器:Iterator
。
把list
、dict
、str
等Iterable
变成Iterator
可以使用iter()
函数
Iterator
的计算是惰性的,只有在需要返回下一个数据时它才会计算
凡是可作用于for
循环的对象都是Iterable
类型;
凡是可作用于next()
函数的对象都是Iterator
类型,它们表示一个惰性计算的序列;
集合数据类型如list
、dict
、str
等是Iterable
但不是Iterator
,不过可以通过iter()
函数获得一个Iterator
对象。
Python的for
循环本质上就是通过不断调用next()
函数实现的
# -*- coding:utf-8 -*- __author__ = 'shisanjun' from collections import Iterable,Iterator #可迭代对象 print(isinstance([],Iterable)) print(isinstance((),Iterable)) print(isinstance((x for x in range(10)),Iterable)) #迭代器 print(isinstance([],Iterator)) print(isinstance((),Iterator)) print(isinstance((x for x in range(10)),Iterator)) #用iter()转换为迭代器 print(isinstance(iter([]),Iterator)) print(isinstance(iter(()),Iterator)) print(isinstance((x for x in range(10)),Iterator))
四.目录组织方式
例子:
假设你的项目名为foo, 比较建议的最方便快捷目录结构这样就足够了:
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
: 项目说明文件。