вопрос для экспертов по Python: код не работает при вызове с генераторами - PullRequest
3 голосов
/ 26 мая 2011

У меня есть небольшой фрагмент кода, который не работает необъяснимым образом.
Цель состоит в том, чтобы сгенерировать все комбинации из двух или более последовательностей.
Он работает при вызове со списками, но не при вызове с генераторами.

def comb(seqs):
    if seqs:
        for item in seqs[0]:
            for rest in comb(seqs[1:]):
                yield [item] + rest
    else:
        yield []

if __name__=="__main__":
    x=[1,2]
    y=[3,4]
    print list(comb([x,y])) # prints [[1, 3], [1, 4], [2, 3], [2, 4]]

    def gen1(): yield 1; yield 2
    def gen2(): yield 3; yield 4
    x=gen1()
    y=gen2()
    print list(comb([x,y])) # prints [[1, 3], [1, 4]  WHY ????

Ответы [ 4 ]

7 голосов
/ 26 мая 2011

Генератор исчерпан, как только он сгенерировал все, что он генерирует, тогда как список можно повторять несколько раз.

Ваш генератор comb полагается на возможность повторения второй и последующих последовательностейчто он передается несколько раз, поэтому не будет работать, если эти последовательности на самом деле являются генератором.

2 голосов
/ 26 мая 2011

Fix:

def comb(seqs):
    if seqs:
        inner = list(comb(seqs[1:]))        
        for item in seqs[0]:
            for rest in inner:
                yield [item] + rest
    else:
        yield []
2 голосов
/ 26 мая 2011

Причина в том, что вы можете перебирать генератор только один раз.В строке

for item in seqs[0]

Когда вы переходите ко второму элементу gen1, вы делаете рекурсивный вызов для перебора элементов gen2.Проблема в том, что вы уже перебрали gen2 в предыдущем рекурсивном вызове, поэтому он не даст никаких элементов.

0 голосов
/ 26 мая 2011

Взгляните на itertools в docs.python.org , там вы, вероятно, найдете все необходимое для создания итераторов для эффективного цикла

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...