简体   繁体   English

将生成器对象转换为列表

[英]Converting generator object to a list

I am trying to wrap my head around generator and yield in python. 我试图把头缠在generator并在python中yield I understand that a function that has an yield returns a generator object. 我知道具有收益的函数会返回生成器对象。 However if I try to convert that generator object to a list it hangs my machine. 但是,如果我尝试将该生成器对象转换为列表,它将挂起我的机器。 I am trying to figure out why that is. 我试图找出原因。 And what is a more elegant way if any to convert a generator object to a list. 还有什么更优雅的方法可以将生成器对象转换为列表。

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))

Output 输出量

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

The problem is that your generator has no end condition ( while True and no break ) 问题是您的生成器没有结束条件( while True且没有break

Even if it could make sense to write such a generator (ex: yield all the decimals of Pi or the Fibonacci sequence I just recognized in your code :)), when you convert it to a list, it loops forever (and eats all the memory too) 即使编写这样的生成器可能有意义(例如:产生Pi或我刚刚在代码中识别的斐波那契序列的所有小数点:)),当您将其转换为列表时,它会永远循环(并吃掉所有记忆也)

BTW: list() is of course the best way to turn a (finite :)) generator to a list object. 顺便说一句: list()当然是将(finite :))生成器转换为list对象的最佳方法。

list() can't convert an infinite sequence. list()无法转换无限序列。 You need to add an upper limit to your generator: 您需要为生成器添加一个上限:

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

print list(fib(10))

Since your generator does not have an upper limit, asking a list of it is like asking to list all the numbers of the Fibonacci sequence (which, as was pointed before, is infinite, so it might take some time :)). 由于您的生成器没有上限,因此询问它的列表就像询问列出斐波那契数列的所有数字(如前所述,它是无限的,因此可能要花一些时间:))。

So, either put an argument in your fib() generator as explained in another post too, or use something like that for the, say, 10 next values: 因此,也可以按照另一篇文章中的说明,在您的fib()生成器中添加一个参数,或者对10个下一个值使用类似的参数:

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

The problem is your generator - list(fib()) basically goes through all iterations of the generator and places them in a list. 问题是您的生成器list(fib())基本遍历了生成器的所有迭代并将它们放置在列表中。 Since your generator is an infinite loop, the iterations never stop. 由于生成器是一个无限循环,因此迭代永远不会停止。

As others have said, your generator will run infinitely. 正如其他人所说,您的生成器将无限运行。 If you tried to convert an infinite generator to a list, it would run ou of memory. 如果您尝试将无限生成器转换为列表,则它将占用内存。 The reason you're getting the output you are is because you need to use next() (which was .__next__ in Python 2) to get the next element from the generator. 获得输出的原因是因为您需要使用next() (在Python 2中为.__next__ )来从生成器获取下一个元素。 eg. 例如。

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


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

But you seem to want to create an entire iterable from your generator, in which case you cannot. 但是您似乎想从生成器中创建一个完整的可迭代对象,在这种情况下您将无法创建。 Python will run out of memory. Python将耗尽内存。 If you want to convert your generator to a list, it must have an upper limit. 如果要将生成器转换为列表,则它必须有一个上限。

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


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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM