Ist generator.next () in Python 3 sichtbar?

247

Ich habe einen Generator, der eine Serie generiert, zum Beispiel:

def triangle_nums():
    '''Generates a series of triangle numbers'''
    tn = 0
    counter = 1
    while True:
        tn += counter
        yield tn
        counter += + 1

In Python 2 kann ich folgende Aufrufe tätigen:

g = triangle_nums()  # get the generator
g.next()             # get the next value

Wenn ich jedoch in Python 3 dieselben zwei Codezeilen ausführe, wird der folgende Fehler angezeigt:

AttributeError: 'generator' object has no attribute 'next'

Die Loop-Iterator-Syntax funktioniert jedoch in Python 3

for n in triangle_nums():
    if not exit_cond:
       do_something()...

Ich konnte noch nichts finden, was diesen Verhaltensunterschied für Python 3 erklärt.

Jottos
quelle

Antworten:

406

g.next()wurde umbenannt in g.__next__(). Der Grund dafür ist die Konsistenz: Spezielle Methoden wie __init__()und __del__()alle haben doppelte Unterstriche (oder "Dunder" in der aktuellen Umgangssprache) und .next()waren eine der wenigen Ausnahmen von dieser Regel. Dies wurde in Python 3.0 behoben. [*]

Aber anstatt anzurufen g.__next__(), verwenden Sie next(g).

[*] Es gibt andere spezielle Attribute, die dieses Update erhalten haben. func_nameIst jetzt __name__, usw.

Lennart Regebro
quelle
Gibt es eine Idee, warum Python 2 die Dunder-Konvention für diese Methoden überhaupt vermieden hat?
Rick unterstützt Monica
Das ist wahrscheinlich nur ein Versehen.
Lennart Regebro
Was ist, wenn Sie __ str __ im Unterricht überschreiben? Ändert es str (obj) oder __str __ (obj)?
NoName
@NoName Es gibt so etwas nicht __str__(obj), also verstehe ich die Frage nicht wirklich.
Lennart Regebro
1
@NoName Ja, das tust du.
Lennart Regebro
144

Versuchen:

next(g)

Schauen Sie sich diese übersichtliche Tabelle an , die die Unterschiede in der Syntax zwischen 2 und 3 zeigt, wenn es darum geht.

Paolo Bergantino
quelle
1
@ MaikuMori Ich habe den Link behoben (Warten auf Peer-Revision) (Die Site diveintopython3.org scheint nicht verfügbar zu sein. Die Mirror-Site diveintopython3.ep.io ist noch am Leben)
Gecco
1
Der Link wurde wieder behoben. python3porting.com/differences.html ist übrigens vollständiger.
Lennart Regebro
Gibt es eine Rechtfertigung für den Wechsel von einer Methode zu einer Funktion, die darüber hinaus g.next()eigentlich sein sollte g.__next__(), und wir brauchen etwas, das keine dumme Methode mit der Funktionalität von ist g.next()?
TC Proctor
11

Wenn Ihr Code unter Python2 und Python3 ausgeführt werden muss, verwenden Sie die 2to3 Six- Bibliothek wie folgt :

import six

six.next(g)  # on PY2K: 'g.next()' and onPY3K: 'next(g)'
Danius
quelle
18
Dies ist nur dann erforderlich, wenn Sie Python-Versionen vor 2.6 unterstützen müssen. Python 2.6 und 2.7 haben die nexteingebaute Funktion.
Mark Dickinson