Python的迭代器、 生成器和修饰器
1、 迭代器是访问集合元素的一种方式,从第一个到最后,只许前进不许后退。
优点:不要求事先准备好整个迭代过程中的所有元素,仅仅在迭代到某个元素时才计算该元素,而在这之前或者之后,元素可以不存在或被销毁。
特点:
- 访问者是不需要关心迭代器内部的结构,仅需要通过next()方法不断去取下一个内容。
- 不能随机访问集合中的某个值,只能从头到尾依次访问。
- 访问到一半时不能往回退
- 便于循环比较大的数据集合,节省内存
1 names = iter(['alex','jack','list']) 2 print(names) 3 print(names.__next__()) 4 print(names.__next__()) 5 print(names.__next__())
结果:
<list_iterator object at 0x005CC410>
alex
jack
list
2、 生成器
定义:
一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会发生生成器。
作用:
这个yield的主要效果,就是可以使函数中断,并保存中断状态,中断后,代码可以继续往下执行,过一段时间还可以再重新调用这个函数,从上次yield的下一句开始执行。
例1:
1 def cash_money(amount): 2 while amount > 0: 3 amount -= 100 4 yield 100 5 print("取钱啦again") 6 atm = cash_money(500) 7 print(type(atm)) 8 print(atm.__next__()) 9 print(atm.__next__()) 10 print("go to 相声") 11 print(atm.__next__())
结果:
<class 'generator'>
100
取钱啦again
100
go to 相声
取钱啦again
100
一共五百块,先去两百块钱,然后去听相声,之后在回来取100 。 一个循环我可以先跳出去做其他事,然后再回来继续做这件事。
例2:用yield实现单线程中的异步
1 import time 2 def consumer(name): 3 print("%s 准备吃包子啦!"%name) 4 while True: 5 baozi=yield #接收别人发送给他的值 6 print("包子%s 来了,被%s吃了!" % (baozi,name)) 7 8 def producer(name): 9 c = consumer('A') 10 c2 = consumer('B') 11 c.__next__() 12 c2.__next__() 13 print("准备做包子啦") 14 for i in range(10): 15 time.sleep(1) 16 print("I finished two baozi!") 17 c.send('Alex')#通过send给yield发送i 18 c2.send(i) 19 20 producer("Young")
可以设置断点,单步运行查看程序运行的过程
3、 装饰器
开放封闭原则:已实现的功能代码不允许被修改,但是可以被扩展
开放:对扩展开放
封闭:以实现的功能代码块
没有使用装饰器
1 def login(func): 2 print("登录验证.") 3 return func 4 5 def home(name): 6 print("Welcome [%s] to home page"%name) 7 def tv(name): 8 print("Welcome [%s] to tv page"%name) 9 def movie(name): 10 print("Welcome [%s] to movie page"%name) 11 tv = login(tv) 12 tv("Young")
结果:
登录验证.
Welcome [Young] to tv page
使用装饰器:
1 def login(func): 2 def inner(arg): 3 print("登录验证.") 4 func(arg) 5 return inner 6 7 def home(name): 8 print("Welcome [%s] to home page"%name) 9 10 @login # 程序一执行就相当于执行tv = login(tv) 11 def tv(name): 12 print("Welcome [%s] to tv page"%name) 13 def movie(name): 14 print("Welcome [%s] to movie page"%name) 15 #tv = login(tv)#相当于@login 16 tv("Young")
返回值
1 def login(func): 2 def inner(*args,**kwagrs): 3 print("登录验证.") 4 return func(*args,**kwagrs) 5 return inner 6 7 def home(name): 8 print("Welcome [%s] to home page"%name) 9 10 @login # 程序一执行就相当于执行tv = login(tv) 11 def tv(name,passwd=123): 12 print("Welcome [%s] to tv page"%name) 13 return 4 14 @login 15 def movie(name): 16 print("Welcome [%s] to movie page"%name) 17 #tv = login(tv)#相当于@login 18 ret = tv("Young",passwd=123) 19 print(ret) 20 movie("Young")
以下部分一是对上述内容中装饰器的解释和补充,另一个视为下面的复杂应用做铺垫。
1 def w1(main_func): 2 def outer(request,kargs): 3 print('before') 4 main_func(request,kargs) 5 print('after') 6 return outer 7 @w1 8 def show(): 9 pass
解析:
首先开始执行@w1,然后执行def w1(main_func):。
对于def w1(main_func): 主要包括两部分内容 def outer(request,kargs): 和 return outer 两个部分,对于def outer(request,kargs): 只是函数定义,没有调用,所以不会执行函数内容;然后执行return outer 返回outer。然后show函数被重新定义,即w1(show)的返回值outer = 新 show 。
以下内容详细看看(作为理解即可,很多时候用不到):
1 def Filter(before_func,after_func): 2 def outer(main_func): 3 def wrapper(request,kargs): 4 before_func(request,kargs) 5 main_func(request,kargs) 6 after_func(request,kargs) 7 return wrapper 8 return outer 9 10 @Filter(before,after) 11 def Index(request,kargs): 12 print('Index')
- 执行Filter(before,after),注意是Filter而不是@,而Filter()的内容是def outer()和return outer(注:这里outer并没有被调用,所以函数的内容并没有执行)
- 因为1、 的返回值是outer ,所以开始执行@outer,@outer会将index作为参数,开始执行到def outer():(但是wrapper函数内容并没有执行),接下来执行return wrapper ,即返回值是wrapper
- 此时新的Insex = wrapper, 最后执行的Index=新Index