python之生成器

  1. 列表生成式
    s = [x*2 for x in range(10)]
    print(s)

    生成一个列表 

  2. 生成器 
s = (x*2 for x in range(5))
print(s)  # <generator object <genexpr> at 0x000002942F46CA20>

创建了一个生成器,但只是一个生成器,生成器里并没有内容。(如果说列表生成式是厨师做了十道菜,这十道菜已经做出来了,占用了空间,那么生成器就是只有厨师,厨师可以做这十道菜,但是还没做,而且厨师只能按照顺序一道一道地做这十道菜,不能不按照顺序做。) 

 “做这些菜”的操作是next()方法,每调用一次就做一次。做完了还调用就会报错。

print(s.__next__())  # 不建议这样调用
print(next(s))  # 等价于s.__next__()  in Py2: s.next()   打印0
print(next(s))  # 打印2
print(next(s))  # 打印4
print(next(s))
print(next(s))
print(next(s))  #  报错 StopIteration

也可以通过 for循环来获取这些“菜”,生成器是一个可迭代对象。

生成器就是一个可迭代对象(iterable)
for i in s:
    print(i)

3. 通过创建一个生成器函数的方式创建生成器

创建一个生成器(生成器实际上就是一个函数)
def foo():
    print('ok')
    yield 1  # 类似于return的功能,把1返回

    print('ok2')
    yield 2

    return None

foo()就是一个生成器对象
print(foo())  # <generator object foo at 0x00000274292E7B88>  没有打印出来'ok'
g = foo()  # 这一句的作用就是创建了一个生成器对象
next(g)
next(g)

需要注意的是,运行上述代码,只会打印‘ok’和'ok2',其中的yield 的作用是返回,yield 1是返回了1,但是这个1并没有print语句打印,就像是return 1之后,需要调用print()函数才会打印出来。

a = next(g)
b = next(g)
print(a, b)

如果将上面代码的两个next(g)语句去掉,调用下面的这三条语句,实验结果如图所示,a,b是yield返回的1和2。

for i in foo():
    print(i)

生成器对象foo()仍然可以通过for进行迭代。for循环后面加的都是可迭代的对象(什么是可迭代对象,只要对象拥有.__iter__()方法,该对象就是可迭代对象。)

 

利用生成器来实现斐波那契函数。

def fib(max):
    n, before, after = 0, 0, 1
    while n < max:
        # print(after)
        yield after
        before, after = after, before+after
        n = n + 1

g = fib(8)
for i in g:
    print(i)

在斐波那契数列中,我们每次打印的是after,也就是说把每次计算得到的after返回就可以。但是每次返回后还要保证下一次 能够继续从该位置执行,所以用yield返回。

 

生成器中send的用法

def bar():
    print('ok1')
    count = yield 1
    print(count)

    print('ok2')
    yield 2

b = bar()
# next(b)

s = b.send(None)  # 等价于next(b)   第一次send前如果没有next,只能传一个send(None)
print(s)
ret = b.send('eee')  # ret是2
print(ret)

整个流程是b=bar(),取得了生成器b,然后b.send(None)进入了bar()函数中,在yield 1处返回1给s,并打印s。b.send('eee')语句再次进入bar(),然后从count = yield 1处继续执行,yield 1 已经执行过了,所以这里从赋值开始执行,将‘eee’赋值给count并打印。然后打印‘ok2’,并返回2给ret打印。 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值