Python学习——迭代器&生成器&装饰器
一、迭代器
迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合
特点:
- 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
- 不能随机访问集合中的某个值 ,只能从头到尾依次访问
- 访问到一半时不能往回退
- 便于循环比较大的数据集合,节省内存
生成一个迭代器:
1 >>> a= iter([1,2,3,4,5]) 2 >>> a 3 <list_iterator object at 0x0044ADF0> 4 5 >>> a.__next__() 6 1 7 >>> a.__next__() 8 2 9 >>> a.__next__() 10 3
二、生成器
一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器
代码:
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 ''' 4 # @time : 2017/4/22 1:00 5 # @author : huange 6 # @version : 1.1 7 # @file : test2.py 8 # @Software: PyCharm 9 ''' 10 11 def out_money(totle): 12 13 while totle > 0: 14 15 totle -= 1 16 17 yield 1 # yield 返回一个值 18 19 20 ATM = out_money(3) 21 22 print("取到钱 %s 万" % ATM.__next__()) 23 24 print("花掉花掉!") 25 26 print("取到钱 %s 万" % ATM.__next__()) 27 28 print("花掉花掉!") 29 30 print("取到钱 %s 万" % ATM.__next__()) 31 32 print("花掉花掉!") 33 34 print("取到钱 %s 万" % ATM.__next__()) # 到这时钱就取没了,再取就报错了 35 36 print("取到钱 %s 万" % ATM.__next__())
这个yield的主要效果呢,就是可以使函数中断,并保存中断状态,中断后,代码可以继续往下执行,过一段时间还可以再重新调用这个函数,从上次yield的下一句开始执行。
可以通过yield实现在单线程的情况下实现并发运算效果
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 ''' 4 # @time : 2017/4/22 1:00 5 # @author : huange 6 # @version : 1.1 7 # @file : test2.py 8 # @Software: PyCharm 9 ''' 10 11 import time 12 13 def consumer(name): 14 print("%s 准备吃包子了!" %name) 15 while True: 16 baozi = yield # yield 通过 send()方法接收值 17 print("包子[%s]来了,被[%s]吃了" %(baozi,name)) 18 19 def producer(name): 20 c1 = consumer('A') 21 c2 = consumer('B') 22 c3 = consumer('C') 23 24 c1.__next__() 25 c2.__next__() 26 c3.__next__() 27 28 print("%s 开始准备做包子了!" % name) 29 30 for i in range(10): 31 time.sleep(1) 32 print('做了3个包子') 33 c1.send(i) 34 c2.send(i) 35 c3.send(i) 36 37 producer('hh')
三、装饰器
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 ''' 4 # @time : 2017/4/24 20:29 5 # @author : huange 6 # @version : 1.1 7 # @file : 装饰器.py 8 # @Software: PyCharm 9 ''' 10 11 # @login内部会执行一下操作: 12 # 1.执行login函数,并将 @login 下面的 函数 作为login函数的参数,即:@login 等价于 login(movie) 13 # 2.•将执行完的 login 函数返回值赋值给@login下面的函数的函数名 14 15 def login(func): 16 def inner(*args,**kwargs): 17 print("login success...") 18 return func(*args,**kwargs) 19 return inner 20 21 def home(): 22 print("welcome to Home...") 23 24 25 @login 26 def movie(name,passwd): 27 print("welcome [%s] [%s] to movie...." % (name,passwd)) 28 29 @login 30 def music(name): 31 print("welcome [%s] to music..." % name) 32 33 movie('huhuan','123') 34 music('huhuan') 35 home()
如上所示:被装饰的函数带有不同个数的参数,因此,装饰器需要用到动态参数!
一个函数可以被多个装饰器装饰:
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 ''' 4 # @time : 2017/4/24 20:29 5 # @author : huange 6 # @version : 1.1 7 # @file : 装饰器.py 8 # @Software: PyCharm 9 ''' 10 # 验证登陆 11 def login(func): 12 def inner(*args,**kwargs): 13 print("login success...") 14 return func(*args,**kwargs) 15 return inner 16 17 # 验证是否是会员用户 18 def member(func): 19 def inner(*args,**kwargs): 20 print("welcome member...") 21 return func(*args,**kwargs) 22 return inner 23 24 def home(): 25 print("welcome to Home...") 26 27 # @login内部会执行一下操作: 28 # 1.执行login函数,并将 @login 下面的 函数 作为login函数的参数,即:@login 等价于 login(movie) 29 # 2.•将执行完的 login 函数返回值赋值给@login下面的函数的函数名 30 @login 31 @member 32 def movie(name,passwd): 33 print("welcome [%s] [%s] to movie...." % (name,passwd)) 34 35 @member 36 @login 37 def music(name): 38 print("welcome [%s] to music..." % name) 39 40 movie('huhuan','123') 41 music('huhuan') 42 home()
装饰器中带有参数:
1 # 认证函数 2 def auth(request,kargs): 3 print("认证成功!") 4 # 日志函数 5 def log(request,kargs): 6 print("日志添加成功") 7 # 装饰器函数。接收两个参数,这两个参数应该是某个函数的名字。 8 def Filter(auth_func,log_func): 9 # 第一层封装,f1函数实际上被传递给了main_fuc这个参数 10 def outer(main_func): 11 # 第二层封装,auth和log函数的参数值被传递到了这里 12 def wrapper(request,kargs): 13 # 下面代码的判断逻辑不重要,重要的是参数的引用和返回值 14 before_result = auth(request,kargs) 15 if(before_result != None): 16 return before_result; 17 18 main_result = main_func(request,kargs) #需要装饰的函数 19 if(main_result != None): 20 return main_result; 21 22 after_result = log(request,kargs) 23 if(after_result != None): 24 return after_result; 25 26 return wrapper 27 return outer 28 # 注意了,这里的装饰器函数有参数,它的意思是先执行filter函数 29 # 然后将filter函数的返回值作为装饰器函数的名字返回到这里,所以, 30 # 其实这里,Filter(auth,log) = outer , @Filter(auth,log) = @outer 31 @Filter(auth,log) 32 def f1(name,age): 33 34 print("%s 正在连接业务部门1数据接口......"%name) 35 36 # 调用方法 37 f1("jack",18) 38 39 结果: 40 认证成功! 41 jack 正在连接业务部门1数据接口...... 42 日志添加成功