简述python三神器——装饰器、迭代器、生成器

    技术2024-07-25  16

    装饰器

    在不修改函数的情况下,给函数添加新的功能。

    闭包: 局部函数的内部函数里,对局部函数的变量进行引用,那么内部函数认为是闭包(closure)

    什么是装饰器

    装饰器(decorator) 的本质就是一个函数, 是增强函数或类的功能的一个函数。 装饰器是一个实参高阶函数也是返回值高阶函数。

    简单装饰器

    def cp(fn): def do_action(name, age, clock): if clock < 21: fn(name, age, clock) else: print('太晚了,不能玩了!') return do_action @cp def play_game(name, game, clock): print(f'{name}再玩会吧!{game}') play_game('乌曼巴', 'balL', 20) """ 乌曼巴再玩会吧!balL """ play_game('得分手', '王者荣耀', 23) """ 太晚了,不能玩了! """

    注意:@符号是装饰器的语法糖

    常见的内置装饰器有三种,@property、@staticmethod、@classmethod

    语法糖

    ​ 语法糖(Syntactic sugar): 添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。语法糖提供了更易读的编码方式,可以提高开发效率。

    迭代器

    可迭代对象

    可迭代对象: 重写了__iter__方法就是可迭代对象

    对象实现了__iter__方法__iter__方法返回了一个迭代器对象

    迭代器对象(迭代器-iterator)

    迭代器对象: 实现了迭代器协议的对象。

    对象实现了__next__方法__next__方法返回了某个数据(我们需要的是返回这个对象的特定的数据,并且按照一定的顺序进行依次返回)__next__方法需要在值取完的时候,抛出StopIteration的错误信息。生成器亦是迭代器 # 只要重写了__iter__方法就是可迭代对象 # 实现了__next__方法。 class Demo(object): def __init__(self, x): self.x = x self.count = 0 def __iter__(self): return self def __next__(self): self.count += 1 if self.count <= self.x: return self.count - 1 else: raise StopIteration d = Demo(10) for i in d: print(i) """ 0 1 2 3 4 5 6 7 8 9 """ # 调用对象方法 # print(d.__iter__().__next__()) """ 上面的for循环已经该迭代器对象把数据遍历完了 raise StopIteration StopIteration """ # 内置函数调用 i=iter(d) print(next(i)) """ raise StopIteration StopIteration """

    生成器—generator

    生成器就是可迭代对象,自动实现了迭代器协议,也可以这样说 在函数中有yield关键字的 就称为 生成器 。

    yield关键字作用:

    保存当前运行状态(断点),然后暂停执行,即将生成器(函数)挂起将yield关键字后面表达式的值作为返回值返回,此时可以理解为起到了return的作用

    next()函数也能让生成器从断点处继续执行,即唤醒生成器(函数)

    斐波那契数列生成器

    def fibonacci(n): current = 0 num1 = num2 = 1 num = 1 while current < n: num = num1 num1, num2 = num2, num1 + num2 current += 1 # return yield num f1 = fibonacci(12) print(f1) for i in f1: print('fibonacc:', i) """ <generator object fibonacci at 0x00000233D485C848> fibonacc: 1 fibonacc: 1 fibonacc: 2 fibonacc: 3 fibonacc: 5 fibonacc: 8 fibonacc: 13 fibonacc: 21 fibonacc: 34 fibonacc: 55 fibonacc: 89 fibonacc: 144 """

    send唤醒

    使用send()函数可以在唤醒的同时向断点处传入一个附加数据,但是不能将非none值发送到刚刚启动的生成器。(即send()函数值为非None值,则不能第一个传入生成器中)

    执行到yield时,gen函数作用暂时保存,返回i的值; temp接收下次c.send(“python”),send发送过来的值,c.next()等价c.send(None)。

    错误实例

    def gen(): i = 0 while i < 5: temp = yield i print(temp) i += 1 g = gen() print(g) print(g.send('hello')) # TypeError: can't send non-None value to a just-started generator

    正确实列

    def gen(): i = 0 while i < 5: temp = yield i print(temp) i += 1 g = gen() print(g) print(g.send(None)) """ <generator object gen at 0x0000029BE6153F48> 0 """ def gen(): i = 0 while i < 5: temp = yield i print(temp) i += 1 g = gen() print(g) print(next(g)) print(g.send('乌曼巴')) """ <generator object gen at 0x0000027DB3B93F48> 0 乌曼巴 1 """
    Processed: 0.027, SQL: 9