2016-11-22 5 views
1

Я пытаюсь обернуть голову вокруг generator и yield в python. Я понимаю, что функция, имеющая доход, возвращает объект-генератор. Однако, если я попытаюсь преобразовать этот объект генератора в список, он висит на моей машине. Я пытаюсь понять, почему это так. И что является более элегантным способом, если есть, чтобы преобразовать объект-генератор в список.Преобразование объекта генератора в список

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

ответ

3

Проблема в том, что ваш генератор не имеет граничное условие (while True и не break)

Даже если это может иметь смысл, чтобы написать такой генератор (например: выход все десятичные знаки Pi или последовательность Фибоначчи, которую я только что узнал в вашем коде :)), когда вы конвертируете ее в список, она навсегда зацикливается (и тоже ест всю память)

BTW: list() - это, конечно, лучший способ превратить генератор (конечный :)) в объект list.

1

Проблема заключается в том, что ваш генератор - list(fib()) в основном проходит через все итерации генератора и помещает их в список. Поскольку ваш генератор представляет собой бесконечный цикл, итерации никогда не останавливаются.

3

list() не может преобразовать бесконечную последовательность. Вам нужно добавить верхний предел вашего генератора:

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

print list(fib(10)) 
+0

Я не встречал '_' внутри цикла for. что это значит? – liv2hak

+2

@ liv2hak Это в основном означает, что вам не нужна переменная, вам просто нужно повторить что-то _n_ количество раз, когда _n_ является номером, указанным в 'range()'. –

+0

@Sven - интересно. спасибо :) – liv2hak

3

Поскольку ваш генератор не имеет верхнего предела, задавая список его как просят перечислить все числа последовательности Фибоначчи (которая, как это было заостренный до, бесконечен, так что это может занять некоторое время :)).

Итак, либо положить аргумент в вашей выдумке() генератор, как описано в другом посте тоже, или использовать что-то подобное для, скажем, 10 следующих значений:

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

Это означает, что генератор реализует интерфейс '__next__' так же, как итератор делает. спасибо, получил – liv2hak

+0

@ liv2hak все генератор, предположим, это удобный способ определения итераторов. –

1

Как уже сказали, ваш генератор будет работать бесконечно. Если вы попытаетесь преобразовать бесконечный генератор в список, он будет запускать память. Причина, по которой вы получаете вывод, заключается в том, что вам нужно использовать next() (который был .__next__ в Python 2), чтобы получить следующий элемент от генератора. например.

>>> 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 
Смежные вопросы