Frage

Hey alle, ich war auf einem rekursiven Generator arbeiten, um die festen ganzzahligen Partitionen einer Zahl zu schaffen, und ich wurde von einer Scoping-Ausgabe verwirrt.

Der Code ist ähnlich wie diese Schnipsel.

def testGen(a,n):
    if n <= 1:
        print('yield', a)
        yield a
    else:
        for i in range(2):
            a[i] += n
            for j in testGen(a,n-i-1):
                yield j

Meine Verwirrung ist unten dargestellt.

>>> list(testGen([1,2],4))
yield [10, 2]
yield [10, 4]
yield [10, 7]
yield [12, 11]
yield [12, 13]
[[12, 13], [12, 13], [12, 13], [12, 13], [12, 13]]

Ich kann die richtige Antwort einfach erhalten, indem eine Kopie des Arrays (z.B. in a[:] zum rekursiven Aufruf vorbei), aber ich verstehe immer noch nicht das oben beschriebene Verhalten. Warum sind die print-Anweisungen und Ertragswerte anders?

War es hilfreich?

Lösung

Die print-Anweisung zeigt die Liste zu diesem bestimmten Zeitpunkt. Der Code ändert sich die Liste, wie Sie es laufen, also von der Zeit, die Liste am Ende prüfen, Sie seinen Wert dann sehen.

Sie können dies beobachten, indem Schreiten durch:

>>> g = testGen([1,2],4)
>>> g.next()
('yield', [10, 2])   # note brackets in print statement because I'm on python 2.5
[10, 2]
>>> g.next()
('yield', [10, 4])
[10, 4]
>>> g.next()
('yield', [10, 7])
[10, 7]
>>> g.next()
('yield', [12, 11])
[12, 11]
>>> g.next()
('yield', [12, 13])
[12, 13]

Andere Tipps

Ich würde vermuten Sie das Array mutieren, so dass, wenn Sie drucken es einen bestimmten Wert hat, dann wird das nächste Mal, wenn es gedruckt hat den Wert tatsächlich aktualisiert, und so weiter. Am Ende haben Sie 5 Referenzen auf das gleiche Array, so natürlich Sie den gleichen Wert 5mal haben.

Listen sind veränderbare Objekte, wenn Sie in einer Liste übergeben, und der Generator führt in-Place-Operationen auf dieser Liste, dann schließlich alle Verweise auf die Liste auf die gleiche Liste verweisen.

Die Druck- und Ertrag Aussagen sind anders, weil Sie nur eine print-Anweisung haben, während Sie 2 Erträge haben. Versuchen Sie folgendes:

def testGen(a,n):
    if n <= 1:
        print('yield', a)
        yield a
    else:
        for i in range(2):
            a[i] += n
            for j in testGen(a,n-i-1):
                print('yield', j)
                yield j

>>> list(testGen([1,2],4))
('yield', [10, 2])
('yield', [10, 2])
('yield', [10, 2])
('yield', [10, 2])
('yield', [10, 4])
('yield', [10, 4])
('yield', [10, 4])
('yield', [10, 4])
('yield', [10, 7])
('yield', [10, 7])
('yield', [10, 7])
('yield', [12, 11])
('yield', [12, 11])
('yield', [12, 11])
('yield', [12, 13])
('yield', [12, 13])
('yield', [12, 13])
[[12, 13], [12, 13], [12, 13], [12, 13], [12, 13]]

Sie werden sehen, dass die letzten Renditen Ihre Antworten sind, weil Sie um die gleiche Liste gegeben worden sind, anstatt eine Kopie zu machen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top