python基础学习(四)-- 生成器(generator)

作者:Shine 发布于:2018-06-29 17:32:15 浏览:869次 分类:PHP

python基础学习(四)-- 生成器(generator)

# 通过列表生成式 可以直接创建一个列表 但是 收到内存限制 列表容量肯定是有限的 而且 创建一个包含100万个元素的列表,不仅会占用很大的内存 如果我们只需要使用前些个元素 那后面的元素占用的空间就白费了
# 如果列表元素可以按照某种算法算出来, 并在循环的过程中不断推算出后续的元素,这样就不必创建完整的list 从而节省大量的空间, python中 这样一边循环一边计算的机制 称之为生成器 即generator

# 创建一个generator的方法:
# 一 只要吧列表生成式的【】改为() 就创建了一个generator

print([x * x for x in range(11)])

print((x * x for x in range(11)))

# 两者仅有的区别就是最外层的【】和() 前者是一个list 而后者就是一个generator

# generator 可以通过next()函数获得generator的下一个返回值 在没有更多的元素时 会抛出StopIteration错误 不过一直使用next()调用有些变态 正确方法是使用for循环 因为generator也是可迭代对象
for n in (x * x for x in range(11)):
    print(n)


# 所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。

# 比如,著名的斐波拉契数列(Fibonacci),***除第一个和第二个数外,任意一个数都可由前两个数相加得到*****,斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:


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


fib(6)


# 其实这里的fib函数已经很接近generator。要把fib函数变为generator,只需要吧print(b)改为yield b就可以了
# 二、这就是定义generator的第二中方法。如果一个函数中包含yield关键字,那么这个函数就不是一个普通函数,而是一个generator

def fib_generator(m):
    n, a, b = 0, 0, 1
    while n < m:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'


# 函数是顺序执行 遇到return语句或者最后一行函数语句就返回。而generator在每次调用next()的时候执行, 遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行

# 调用generator时 首先要生成一个generator对象 然后使用next()函数不断获得下一个返回值, ***同样的,函数改成的generator 基本不会使用next 去获取下一个返回值 而是使用for循环进行迭代

o = fib_generator(6)
# print(next(o))

# 但是在使用for循环调用generator,发现拿不到generator的return语句的返回值,如果想要拿到返回值 必须捕捉StopIteration错误,返回值包括在StopIteration的value中

while True:
    try:
        x = next(o)
        print('value is:',  x)
    except StopIteration as e:
        print('generator return value :',  e.value)
        break


# practice: 试用generator不断输出杨辉三角下一行的list
#                   1
#                  / \
#                 1   1
#                / \ / \
#               1   2   1
#              / \ / \ / \
#             1   3   3   1
#            / \ / \ / \ / \
#           1   4   6   4   1
#          / \ / \ / \ / \ / \
#         1   5   10  10  5   1



def triangles():
    N = [1]
    while True:
        yield N
        N.append(0)
        N = [N[i - 1] + N[i] for i in range(len(N))]


n = 0
for t in triangles():
    print(t)
    n = n + 1
    if n == 10:
        break

# 解析:
# n = 2
# 时, N = [1, 0]
#
# range(len(N)) = [0, 1]
#
# 即:N = [N[i - 1] + N[i] for i in [0, 1]]
# 即:N = [N[0 - 1] + N[0], N[1 - 1] + N[1]]
# 即:N = [0 + 1, 1 + 0] = [1, 1]




def triangles1():
    a = [1]
    while True:
        yield a
        a = [sum(i) for i in zip([0] + a, a + [0])]


n = 0
for t in triangles1():
    print(t)
    n = n + 1
    if n == 10:
        break

# zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
# 例如: a = [1, 2, 3]  b = [4, 5, 6]
# zip(a, b) == > [(1, 4), (2, 5), (3, 6)]


标签: python generator
声明:文章内容由作者原创或整理,转载请标明出处!
暂留位置!--请勿随意修改