生成器:
创建python迭代器的过程虽然强大,但是很多时候使用不方便。生成器是一个简单的方式来完成迭代。
简单来说,Python的生成器是一个返回可以迭代对象的函数。
创建生成器:
在一个一般函数中使用yield
关键字,可以实现一个最简单的生成器,
此时这个函数变成一个生成器函数。yield
与return
返回相同的值,
区别在于return
返回后,函数状态终止,而yield
会保存当前函数的执行状态,
在返回后,函数又回到之前保存的状态继续执行。
生成器函数与一般函数的不同:
生成器函数包含一个或者多个yield
当调用生成器函数时,函数将返回一个对象,但是不会立刻向下执行
像__iter__()
和__next__()
方法等是自动实现的,所以我们可以通过next()
方法对对象进行迭代
一旦函数被yield
,函数会暂停,控制权返回调用者
局部变量和它们的状态会被保存,直到下一次调用
函数终止的时候,StopIteraion
会被自动抛出
def gen(): 测试: n = 1 first print("first") 1 yield n second n +=1 2 print("second") third yield n 3 n +=1 print("third") yield n a = gen() print(next(a)) print(next(a)) print(next(a))
print("for:") 测试:first
b = gen() 1
for i in gen(): second
print(i) 2
third
3
更容易使用,代码量较小
内存使用更加高效。比如列表是在建立的时候就分配所有的内存空间,而生成器仅仅是需要的时候才使用,更像一个记录
代表了一个无限的流。如果我们要读取并使用的内容远远超过内存,但是需要对所有的流中的内容进行处理,
那么生成器是一个很好的选择,比如可以让生成器返回当前的处理状态,由于它可以保存状态,那么下一次直接处理即可。
流水线生成器。
闭包:
必须有一个内嵌函数(函数里定义的函数)——这对应函数之间的嵌套
内嵌函数必须引用一个定义在闭合范围内(外部函数里)的变量——内部函数引用外部变量
外部函数必须返回内嵌函数——必须返回那个内部函数
def funa(): 测试: x = 5 6 def funb(): nonlocal x x +=1 return x return funb a = funa() print(a())
以上会发现,funa()中的x变量,原本仅仅是funx的一个局部变量。但是形成了闭包之后,它的行为就好像是一个全局变量一样。但是x并不是全局变量。
(注意我们上面的a=funa(),a实际上应该是funb,所以a称为闭包)
一般情况下,局部变量在函数返回时,就会被垃圾回收器回收,而不能再被使用。但闭包是一种特殊情况,当外函数的的变量在内函数使用时,即绑定给内部函数,延长生命周期
装饰器:
python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,
使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。
原则:
不能修改被装饰函数的源代码。
不能修改被装饰函数的调用方式。
不能改变被装饰函数的执行结果。
装饰器对被装饰函数是透明的
def add (a,b): return a+b def m(a,b): return a*b def checkParams(fn): def wrapper(a, b): if isinstance(a, (int, float)) and isinstance(b, (int, float)): return fn(a, b) #否则通过logging记录错误信息,并友好退出 print("variable 'a' and 'b' cannot be added") return return wrapper w = checkParams(add) s = w(2,3) print(s) a = checkParams(m) b = a(4,5) print(b)
def doupi(fn): def jiadoupi(): print("麻将豆皮10块") return fn()+10 return jiadoupi def xiangcai(fnn): def jiaxiangcai(): print("麻将香菜5块") return fnn()+5 return jiaxiangcai @xiangcai @doupi def diguo(): print("底锅50") return 50 aa=doupi(xiangcai(diguo)) print(aa()) # bb=xiangcai(doupi(diguo)) # print(bb()) x=diguo() print(x)
测试如下:5
6
麻将豆皮10块
麻将香菜5块
麻将香菜5块
麻将豆皮10块
底锅50
80
麻将香菜5块
麻将豆皮10块
底锅50
65