Generator.next () è visibile in Python 3?


247

Ho un generatore che genera una serie, ad esempio:

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

In Python 2 sono in grado di effettuare le seguenti chiamate:

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

tuttavia in Python 3 se eseguo le stesse due righe di codice ottengo il seguente errore:

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

ma la sintassi dell'iteratore di loop funziona in Python 3

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

Non sono ancora riuscito a trovare nulla che spieghi questa differenza di comportamento per Python 3.

Risposte:


406

g.next()è stato rinominato in g.__next__(). La ragione di ciò è la coerenza: metodi speciali come __init__()e __del__()tutti hanno doppi punti di sottolineatura (o "dunder" nell'attuale vernacolo), ed è .next()stata una delle poche eccezioni a quella regola. Questo problema è stato risolto in Python 3.0. [*]

Ma invece di chiamare g.__next__(), usa next(g).

[*] Ci sono altri attributi speciali che hanno ottenuto questa correzione; func_name, è ora __name__, ecc.


qualche idea sul perché python 2 abbia evitato in primo luogo la convenzione dunder per questi metodi?
Rick supporta Monica il

Questa è probabilmente solo una svista.
Lennart Regebro,

Che dire di quando sovrascrivi __ str __ nelle classi? Cambia str (obj) o __str __ (obj)?
NoName

@NoName Non esiste una cosa del genere __str__(obj), quindi non capisco davvero la domanda.
Lennart Regebro,

1
@NoName Sì, lo fai.
Lennart Regebro,

144

Provare:

next(g)

Dai un'occhiata a questa tabella accurata che mostra le differenze di sintassi tra 2 e 3 quando si tratta di questo.


1
@MaikuMori Ho corretto il collegamento (in attesa di revisione tra pari) (Il sito diveintopython3.org sembra essere inattivo. Il sito mirror diveintopython3.ep.io è ancora vivo)
gecco

1
Risolto nuovamente il collegamento. python3porting.com/differences.html è più completo, a proposito.
Lennart Regebro,

C'è qualche giustificazione per il passaggio da un metodo a una funzione, al di là g.next()dovrebbe essere davvero g.__next__(), e dobbiamo avere qualcosa che non sia un metodo noioso con la funzionalità di g.next()?
TC Proctor il

11

Se il codice deve essere eseguito in Python2 e Python3, utilizzare la libreria sei 2to3 in questo modo:

import six

six.next(g)  # on PY2K: 'g.next()' and onPY3K: 'next(g)'

18
Non ce n'è bisogno a meno che non sia necessario supportare versioni di Python precedenti alla 2.6. Python 2.6 e 2.7 hanno la nextfunzione integrata.
Mark Dickinson,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.