生成器

生成器

生成器是一个函数,按照顺序返回一个或多个值。含有关键字yield的函数就是生成器。

def fib(n):
    a = 0
    b = 1
    for i in range(n):
        if not i:
            yield 1
        else:
            a, b = b, a+b 
            yield b 
for i in fib(5):
    print(i)
fiby = fib(5)
for i in range(6):  # next函数可以得到下一个值,当没有值可以返回时,引起StopIteration错误
    print(next(fiby))

生成器之间的交互

生成器协议提供了一个额外的send方法,可以实现生成器的反向沟通。
yield语句实际上是一个表达式,可以用send方法赋值给yield表达式的结果

def fun():
    var = yield 3
    print(f"send({var})")
    yield var
    

f = fun()
print(next(f))  # 3
print(f.send("a"))
# send(a)
# a
def square(n = 1):
    while True:
        var = yield n**2  # 默认情况下yield表达式的结果为None,当
        # 调用send函数时,send的实参会赋值给var,从而影响生成器
        if var:
            n = var 
        else:
            n+=1

sq = square()
print(next(sq))  # 1
print(next(sq))  # 4
print(sq.send(5))  # 25 , send把5赋值给var
print(next(sq))   # 36
print(next(sq))   # 49
def sq2(n=1):
    while True:
        res = yield n**2
        n+=1
        if res:
            yield res**2
        
sq = sq2()
print(next(sq))  # 1
print(next(sq))  # 4
print(sq.send(5))  # 25 , send把5赋值给res
print(next(sq))   # 9
print(next(sq))   # 16
import inspect 
import types
range_ = range(3)
zip_ = zip(['a','b'],[1,2])
dic = dict(zip_)
enumerate_ = enumerate(list("abc"))
map_ = map(int, ['1','2'])
for obj in [range_, zip_,enumerate_, map_, dic.keys(),dic.items(),dic.values()]:
    print(obj, "is generator ?", isinstance(obj, types.GeneratorType))
    print(obj, "is generator ?", inspect.isgenerator(obj))

# range(0, 3) is generator ? False
# range(0, 3) is generator ? False
# <zip object at 0x000001C8E84A3580> is generator ? False
# <zip object at 0x000001C8E84A3580> is generator ? False
# <enumerate object at 0x000001C8E84AB9C0> is generator ? False
# <enumerate object at 0x000001C8E84AB9C0> is generator ? False
# <map object at 0x000001C8E8375E20> is generator ? False
# <map object at 0x000001C8E8375E20> is generator ? False
# dict_keys(['a', 'b']) is generator ? False
# dict_keys(['a', 'b']) is generator ? False
# dict_items([('a', 1), ('b', 2)]) is generator ? False
# dict_items([('a', 1), ('b', 2)]) is generator ? False
# dict_values([1, 2]) is generator ? False
# dict_values([1, 2]) is generator ? False

yield from

生成器调用其他生成器

def f1():
    yield 1
    yield 2

def f2():
    yield 'a'
    yield 'b'

def func():
    yield from f1()
    yield from f2()

for i in func():
    print(i)

单例斐波那契数列类

def signleton(cls):
    instance = {}
    def inner(*args, **kwargs):
        if cls not in instance:
            instance[cls] = cls(*args, **kwargs)
        return instance[cls]
    return inner 


@signleton
class Fib:
    def __init__(self) -> None:
        self.numbers = []
    def __iter__(self):
        return self 
    def __next__(self):
        if len(self.numbers)<2:
            self.numbers.append(1)
        else:
            self.numbers.append(sum(self.numbers))
            self.numbers.pop(0)
        return self.numbers[-1]
    def send(self, val):
        pass

f1 = Fib()
f2 = Fib()
print(f1 is f2)  # 单例
print(next(f1))  # 1
print(next(f1))  # 1
print(next(f1))  # 2
print(next(f1))  # 3
print(next(f1))  # 5
print(next(f2))  # 8
posted @ 2022-06-24 13:31  店里最会撒谎白玉汤  阅读(86)  评论(0)    收藏  举报