生成器——一边循环一边计算的机制

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
可以在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。


怎么打印出generator的每一个元素呢:使用for循环


创建一个generator的另一种方法:如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator

斐波拉契数列,用函数把它打印出来:

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print(b)
        a, b = b, a + b
        n = n + 1
    return 'done'

要把fib函数变成generator,只需要把print(b)改为yield b就可以了:

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'
变成generator的函数,在每次调用 next() 的时候执行,遇到 yield 语句返回,再次执行时从上次返回的 yield语句处继续执行。

举个简单的例子,定义一个generator,依次返回数字1,3,5:


def odd():
    print('step 1')
    yield 1
    print('step 2')
    yield(3)
    print('step 3')
    yield(5)
调用该generator时,首先要生成一个generator对象,然后用next()函数不断获得下一个返回值:


>>> o = odd()
>>> next(o)
step 1
1
>>> next(o)
step 2
3
>>> next(o)
step 3
5
>>> next(o)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration


要理解generator的工作原理,它是在for循环的过程中不断计算出下一个元素,并在适当的条件结束for循环。对于函数改成的generator来说,遇到return语句或者执行到函数体最后一行语句,就是结束generator的指令,for循环随之结束。

请注意区分普通函数和generator函数,普通函数调用直接返回结果:

>>> r = abs(6)
>>> r
6

generator函数的“调用”实际返回一个generator对象:

>>> g = fib(6)
>>> g
<generator object fib at 0x1022ef948>
[]是通过遍历可迭代对象生成一个list
()是直接返回可迭代对象


杨辉三角定义如下:

          1
        1   1
      1   2   1
    1   3   3   1
  1   4   6   4   1
1   5   10  10  5   1

把每一行看做一个list,试写一个generator,不断输出下一行的list:

def triangles():
    result = [1]
    while :
        yield result
        l = list(result)
        l.append(0)

        result=[l[i]+l[i-1] for i in range(len(l))]


Python实际上调用了list最后一个元素,list每次append的0,在单行计算的开头和结尾用了两次。
路演一下这行代码。。。。。


输出第2层:
l = [1,0]
result = [l[i]+l[i-1] for i in range(len(l))] 的执行顺序:
i = 0
result[0] = l[0]+l[-1] = 1 + 0 = 1
i = 1
result[1] = l[1]+l[0] = 0 + 1 = 1
result = [1,1]


输出第3层:
l = [1,1,0]
result = [l[i]+l[i-1] for i in range(len(l))] 的执行顺序:
i = 0
result[0] = l[0]+l[-1] = 1 + 0 = 1
i = 1
result[1] = l[1]+l[0] = 1 + 1 = 2
i = 2
result[2] = l[2]+l[1] = 0 + 1 = 1


输出第4层:
l = [1,2,1,0]
result = [l[i]+l[i-1] for i in range(len(l))] 的执行顺序:
i = 0
result[0] = l[0]+l[-1] = 1 + 0 = 1
i = 1
result[1] = l[1]+l[0] = 2 + 1 = 3
i = 2
result[2] = l[2]+l[1] = 1 + 2 = 3
i = 3
result[3] = l[3]+l[2] = 0 + 1 = 1


………………

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值