将生成器对象转换为列表

时间:2016-11-22 21:51:34

标签: python generator

我试图在python中围绕generatoryield。我知道具有yield的函数返回一个生成器对象。但是,如果我尝试将该生成器对象转换为列表,它会挂起我的机器。我试图找出原因。如果将生成器对象转换为列表,那么更优雅的方法是什么。

def fib():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

a = fib()
print(type(a))

b = fib()
print(type(b))

print(list(b))

输出

<class 'generator'>
<class 'generator'>

5 个答案:

答案 0 :(得分:4)

问题是您的生成器没有结束条件(while True而没有break

即使编写这样的生成器是有意义的(例如:产生Pi的所有小数或我刚刚在代码中识别出的Fibonacci序列:)),当你将它转换为列表时,它永远循环(并且也吃掉所有的记忆)

BTW:list()当然是将(有限:))生成器转换为list对象的最佳方法。

答案 1 :(得分:3)

list()无法转换无限序列。您需要为生成器添加上限:

def fib(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

print list(fib(10))

答案 2 :(得分:3)

由于您的生成器没有上限,因此询问它的列表就像要求列出Fibonacci序列的所有数字(如前所述,它是无限的,因此可能需要一些时间:))

所以,要么在你的fib()生成器中加入一个参数,如另一篇文章中所解释,或者使用类似的东西,例如10个下一个值:

b = fib()
[next(b) for _ in range(10)]

答案 3 :(得分:1)

问题在于您的生成器 - list(fib())基本上遍历生成器的所有迭代并将它们放在列表中。由于您的生成器是无限循环,因此迭代永远不会停止。

答案 4 :(得分:1)

正如其他人所说,你的发电机将无限运行。如果您尝试将无限生成器转换为列表,它将运行内存。您获得输出的原因是因为您需要使用next()(在Python 2中为.__next__)来从生成器获取下一个元素。例如

>>> def gen():
    for i in range(100):
        yield i


>>> g = gen()
>>> next(g)
0
>>> next(g)
1
>>> next(g)
2
>>> 

但是你似乎想要从你的生成器创建一个完整的迭代,在这种情况下你不能。 Python将耗尽内存。如果要将生成器转换为列表,则必须具有上限。

>>> def gen():
    while True:
        yield 0


>>> g = gen()
>>> list(g)
# it gets stuck forever