装饰器和生成器
装饰器:
def hello(fn): #1,3
def wrapper (): #4
fn()
return wrapper #5
@hello #2
def foo():
print("123")
foo() #6
装饰器执行流程如上图所标注的那样:
第一步:执行def hello(fn)。
第二步:执行@hello。此句的意思为:foo = hello(foo),也就是将foo函数作为参数传递给hello函数,再回调
第三步:此时fn=foo
第四步:执行wrapper函数
第五步:返回整个wrapper函数
第六步:foo()=wrapper()。输出wrapper()函数的值,此前因为foo = hello(foo),而执行hello(foo)函数,返回的结果就是wrapper整个函数,所以foo()=wrapper().
重点理解:
1.python中一切皆为对象,函数是第一类对象,所谓第一类对象,意思是可以用标识符给对象命名,并且对象可以被当作数据处理,例如赋值、作为参数传递给函数,或者作为返回值return 等,所以foo函数才可以作为参数去传递,才可以出现return wrapper.
2.foo()和foo的区别,foo是函数,foo()是调用函数后的值,无论是把函数赋值给新的标识符,还是把函数作为参数传递给新的函数,针对的都是函数对象本身,而不是函数的调用。foo 函数对象本身,foo()函数的调用。
生成器:
· 生成器,即生成一个容器。
· 在Python中,一边循环,一边计算的机制,称为生成器。
· 生成器可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他数据类型需要调用自己的内置iter()方法或__iter__()的内置函数),所以,生成器就是一个可迭代对象。
· 在Python中,使用生成器可以很方便的支持迭代器协议
生成器优点:
Python使用生成器对延迟操作提供了支持,所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。
- 生成器是可迭代对象;
- 实现了延迟计算,省内存(按需执行);
- 生成器本质和其他类型一样,都是实现了迭代器协议,只不过生成器是一边计算,一边生成,从而节省内存空间,其余的可迭代对象可没有这个功能。
迭代器协议:生成器自动实现了迭代器协议
迭代器协议是指:对象提供next()方法,它要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代。
可迭代对象:实现了迭代器协议的对象
协议是一种约定,可迭代对象实现迭代器协议,Python的内置工具(for循环、sum、min、max函数等)使用迭代器协议访问对象
在python中,for循环不仅可以遍历列表,也可以遍历文件
with open ('/etc/passwd') as f: for line in f: print(line)
因为文件对象实现了迭代器协议,for循环并不知道它所遍历的是一个文件对象,它只管使用迭代器协议访问对象即可。
注意:生成器只能遍历一次。
例如:
def get_province_population(filename): with open(filename) as f: for line in f: yield int (line) gen = get_province_population('data.txt') all_population = sum(gen) for population in gen: print(population/all_population)
此段代码执行完不会有任何输出,因为在执行到sum时,就已经遍历了生成器,再往下执行时,将不会有任何记录。