生成器,迭代器,装饰器
生成器 (generator)
-
概念
- 在Python中, 一边循环一边计算的机制, 称为生成器: generator 创建生成器: G = ( x*2 for x in range(5)) 可以通过 next(生成器) 函数获得生成器的下一个返回值 没有更多的元素时, 抛出 StopIteration 的异常 生成器也可以使for 循环,因为生成器也是可迭代对象
-
生成器的生成方式1:
list2 = [x for x in range(10)] print(type(list2)) # 得到一个生成器对象 g = (x*2 for x in range(10)) print(type(g)) # 打印生成器生成的第一个数字 print(next(g)) print(next(g)) print(next(g)) 一共10个数字,打印超出报StopIteration异常
- 应用: 求斐波那契数列的第n个数
def fibo(n): a,b=1,1 i = 3 while i <= n: if i == 1 or i == 2: return 1 else: a,b = b,a+b i += 1 else: print(b)
-
生成器的生成方式2(包含yield关键字的函数):
def getNum(): for i in range(10): yield i
-
生成器中元素的访问方式:
- 1.next()
- 2.g.__next()
- 3.g.send('发送的参数')
def gen(): print('a') count = yield 1 print ('--->',count) print ('b') yield 2 #注意打印结果 g = gen() next(g) g.send('123') next(g)
-
其他使用场景:(携程,实现两个任务的交替调用)
def save(): while True: yield print ('save') def draw(): while True: yield print ('draw') g1 = save() g2 = draw() while True: next(g1) next(g2)
迭代器 (Iterator)
- 概念: 拥有__iter__方法和__next__方法的对象就是迭代器
- 迭代
- 迭代是访问集合元素的一种方式,可以将某个数据集内的数据“一个挨着一个的取出来”,就叫做迭代
- 可迭代协议
- 协议就是互相规定好的。可迭代协议的定义非常简单,就是内部实现了 __iter__方法。
- 迭代器协议
- 迭代器协议:必须拥有__iter__方法和__next__方法
- 可以通过dir(对象)查看是否实现了__iter__,__next__等方法来判断对象是否为迭代器
- 也可以使用 isinstance(Iterator)来判断
- 练习:
- 查看__iter__()的返回值
- 查看__iter__()包含的方法
- 分别查看迭代器与列表的方法
- 迭代
- for循环的本质
- 通过__iter__()获取该对象的一个迭代器对象
- 通过__next__()函数,依次获取下一个元素
闭包
- 什么是闭包?
- 在 python 中创建一个闭包一般有 3 个要求:
- 1.闭包函数必须有内嵌函数。
- 2.内嵌函数必须要引用外层函数的变量。
- 3.闭包函数返回内嵌函数的地址(函数名称)
- 在 python 中创建一个闭包一般有 3 个要求:
- 创建一个闭包函数:
def funcOut(): name = 'Jery' def funcIn(): print(name) return funcIn f = funcOut() f()
- 判断是否为闭包函数
def funcOut(): name = 'abc' def funcIn(): print(name) pass #如果打印None,则不是闭包函数 print(funcIn.__closure__) return funcIn f=funcOut() f()
装饰器
- 装饰器的本质:(闭包函数)
- 装饰器的作用:
- 在不修改原函数及其调用方式的情况下对原函数功能进行扩展
- 装饰器的使用:
- 需求:为现有功能fun1增加日志功能
- 传统方案解决
- 使用闭包解决
def outfunc(func): def infunc(): writeLog() func() return infunc def fun1(): print("使用功能1") def fun2(): print("使用功能2") # 注意名字的问题,需要分析 fun1 = outfunc(fun1) # 装饰器(闭包) fun1() 使用装饰器(语法糖)解决 def outfunc(func): def infunc(): writeLog() func() return infunc @outfunc def fun1(): print("使用功能1") @outfunc def fun2(): print("使用功能2") fun1() fun2()
- 多个装饰器的使用
def add1(fc): print("add1正在装饰") def wrapped(): return "《"+fc()+"》" return wrapped def add2(fc): print("add2正在装饰") def wrapped(): return '*'+fc()+'*' return wrapped #看到这个,开始进行装饰,而不是等到调用时 @add1 @add2 def test1(): return '金陵十三钗' print(test1())
- 对有参数的函数进行装饰
def func(fn): print("func") def func_in(aa, bb): print("func_in1") fn(aa,bb) print("func_in2") return func_in @func def test(a, b): print("a=%d,b=%d" % (a, b)) # 装饰器装饰之后,这不是直接调用test方法,而是调用func_in方法 test(1,2)
- 通用装饰器的使用
def func(fn): # 需要有参数,*args,**kwargs def func_in(*args,**kwargs): print("记录日志") print('访问方法:'+fn.__name__) # 需要有参数,*args,**kwargs xx = fn(*args,**kwargs) # 需要有返回值 return xx return func_in
# 待装饰函数:无参数,无返回值
@func def test1(): print("test1") test1() @func def test2(): return "Hello" print(test2()) @func def test3(a): print('a=%d'%a) test3(1)
类方法静态方法
- 静态方法:
- 1.格式:在方法上面添加 @staticmethod
- 2.参数:静态方法可以有参数也可以无参数
- 3.应用场景:一般用于和类对象以及实例对象无关的代码。
- 4.使用方式: 类名.类方法名(或者对象名.类方法名)
- 使用示例: 比如:学生管理系统的展示主菜单
- 类方法:
- 无需实例化,可以通过类直接调用的方法,但是方法的第一个参数接收的一定是类本身
- 1.在方法上面添加@classmethod
- 2.方法的参数为 cls 也可以是其他名称,但是一般默认为 cls
- 3.cls 指向 类对象(也就是 Goods)
- 4.应用场景:当一个方法中只涉及到静态属性的时候可以使用类方法(类方法用来修改类属 性)。
- 5.使用 可以是 对象名.类方法名。或者是 类名.类方法名
- 使用示例:
- 修改所有商品的折扣
class Goods(): discount = 1 def __init__(self,price,name): self.name = name self.price = price def price_discount(self): return self.price * Goods.discount @classmethod def change_discount(cls,new_discount): cls.discount = new_discount
所思及所学
学而不思则罔,思而不学则殆!