2010-07-09 10 views
99

Ich möchteWie verbinden Sie zwei Generatoren in Python?

for directory, dirs, files in os.walk(directory_1): 
    do_something() 

for directory, dirs, files in os.walk(directory_2): 
    do_something() 

zu diesem Code den folgenden Code ändern:

for directory, dirs, files in os.walk(directory_1) + os.walk(directory_2): 
    do_something() 

ich den Fehler:

unsupported operand type(s) for +: 'generator' and 'generator'

Wie zwei Generatoren in Python verbinden?

+1

ich wie Python auch würde auf diese Weise zu arbeiten. Habe genau den gleichen Fehler! –

Antwort

141

Ich denke, itertools.chain() sollte es tun.

+1

http://docs.python.org/library/itertools.html – reto

+3

yep, das ist genau das, was 'chain()' für –

+16

ist Wenn Sie 'itertools.chain' verwenden, um nicht zwei Iterables zu verketten, wie in der Frage, aber alle iterables in einem iterablen (z. B. "chain (* imap (xrange, xrange (5))")), könnten Sie auf [Python Fehler # 4806] (http://bugs.python.org/issue4806), die Maskiert jeden TypeError, der innerhalb des iterablen Objekts ausgelöst wird, und führt zu einer verwirrenden Fehlermeldung. Alternativ können Sie in diesem Fall 'itertools.chain.from_iterable' (seit Python 2.6) verwenden, das die iterierbare Zahl direkt als Argument akzeptiert:' chain.from_iterable (imap (xrange, xrange (5))) '. –

29

Ein Beispiel für Code:

from itertools import chain 

def generator1(): 
    for item in 'abcdef': 
     yield item 

def generator2(): 
    for item in '123456': 
     yield item 

generator3 = chain(generator1(), generator2()) 
for item in generator3: 
    print item 
5

Mit itertools.chain.from_iterable Sie können wie die Dinge tun:

def genny(start): 
    for x in range(start, start+3): 
    yield x 

y = [1, 2] 
ab = [o for o in itertools.chain.from_iterable(genny(x) for x in y)] 
print(ab) 
1

Einfaches Beispiel:

from itertools import chain 
x = iter([1,2,3])  #Create Generator Object (listiterator) 
y = iter([3,4,5])  #another one 
result = chain(x, y) #Chained x and y 
0

Wenn Sie behalten möchten Die Generatoren trennen sich aber iterieren immer noch über sie zur gleichen Zeit können Sie zip() verwenden:

HINWEIS: Iteration stoppt an der kürzeren der beiden Generatoren

Zum Beispiel:

for (root1, dir1, files1), (root2, dir2, files2) in zip(os.walk(path1), os.walk(path2)): 

    for file in files1: 
     #do something with first list of files 

    for file in files2: 
     #do something with second list of files 
0

Lassen Sie uns sagen, dass wir zu Generatoren (Gen1 und Gen2) haben, und wir wollen einige zusätzliche Berechnung ausführen zu können, erfordert das Ergebnis von beiden. Wir können das Ergebnis einer solchen Funktion/Berechnung durch die map-Methode zurückgeben, die wiederum einen Generator zurückgibt, den wir durchlaufen können.

In diesem Szenario muss die Funktion/Berechnung über die Lambda-Funktion implementiert werden. Der schwierige Teil ist, was wir innerhalb der Karte und seiner Lambda-Funktion tun wollen.

Allgemeine Form der vorgeschlagenen Lösung:

def function(gen1,gen2): 
     for item in map(lambda x, y: do_somethin(x,y), gen1, gen2): 
      yield item 
+2

Sie sollten in Erwägung ziehen, einige hilfreiche Erklärungen zu dem, was dies tut, anstelle nur des Codeblocks zu veröffentlichen – AK47

1

In Python3 + können Sie tun:

def concat(a, b): 
    yield from a 
    yield from b