2013-05-29 9 views
104

Considerare:comportamento lista Python iteratore e il prossimo (iterator)

>>> lst = iter([1,2,3]) 
>>> next(lst) 
1 
>>> next(lst) 
2 

Così, avanzando l'iteratore è, come previsto, gestita da una mutazione che lo stesso oggetto.

Stando così, mi aspetto:

a = iter(list(range(10))) 
for i in a: 
    print(i) 
    next(a) 

per saltare ogni secondo elemento: la chiamata a next dovrebbe avanzare l'iteratore volta, la chiamata implicita fatta dal ciclo deve avanzare una seconda volta - e il risultato di questa seconda chiamata verrà assegnato a i.

Non funziona. Il ciclo stampa tutti gli articoli degli elementi nell'elenco, senza saltare nessuno.

Il mio primo pensiero è che questo potrebbe accadere perché il ciclo chiama iter su ciò che è passato, e questo potrebbe dare un iteratore indipendente - questo non è il caso, come abbiamo iter(a) is a.

Quindi, perché non sembra che next avanzi l'iteratore in questo caso?

risposta

137

Quello che vedete è il interprete eco di nuovo il valore di ritorno di next() oltre ad i essere stampato ogni iterazione:

>>> a = iter(list(range(10))) 
>>> for i in a: 
... print(i) 
... next(a) 
... 
0 
1 
2 
3 
4 
5 
6 
7 
8 
9 

Così 0 è l'uscita di print(i), 1 il ritorno valore da next(), echoed dall'interprete interattivo, ecc. Ci sono solo 5 iterazioni, ciascuna iterazione che porta alla scrittura di 2 righe sul terminale.

Se si assegna l'output di next() cose funzionano come previsto:

>>> a = iter(list(range(10))) 
>>> for i in a: 
... print(i) 
... _ = next(a) 
... 
0 
2 
4 
6 
8 

o stampare più informazioni per differenziare il print() uscita dal interattivo eco interprete:

>>> a = iter(list(range(10))) 
>>> for i in a: 
... print('Printing: {}'.format(i)) 
... next(a) 
... 
Printing: 0 
1 
Printing: 2 
3 
Printing: 4 
5 
Printing: 6 
7 
Printing: 8 
9 

In altre parole , next() funziona come previsto, ma poiché restituisce il valore successivo dall'iteratore, riprodotto dall'interprete interattivo, si viene portati a credo che il ciclo abbia in qualche modo la propria copia iterativa.

+8

Non ero a conoscenza di questo comportamento dall'interprete. Sono contento di averlo scoperto prima di perdere un sacco di tempo a chiedermelo mentre risolvo qualche problema reale. – brandizzi

+3

... \ * dies *. Il peggio è che posso ricordare di aver menzionato esattamente questo comportamento di interprete a qualcuno, forse una settimana fa. – lvc

+0

interessante. Ho provato per i in a: next (a); print i e ho pensato di saltare a 1 e stampare 1,3,5,7,9. Ma ancora è 0,2,4,6,8. Perché? – user2290820

2

C'è qualcosa che non va con il tuo Python/Computer.

a = iter(list(range(10))) 
for i in a: 
    print(i) 
    next(a) 

>>> 
0 
2 
4 
6 
8 

funziona come previsto.

Testato in Python 2.7 e in Python 3+. Funziona correttamente sia per

+5

ottengo lo stesso risultato di @lvc (solo su IDLE tuttavia, quando eseguita come lo script ottengo questo)) – jamylak

+3

@Inbar Rose Solo se si esegue come script. – thecoder16

+0

è il comportamento di mettere il codice tramite shell interattiva. Se la funzione restituisce il valore senza essere utilizzato, l'interprete lo stamperebbe in shell come output di debug – Reishin

10

Che cosa sta succedendo è che next(a) restituisce il valore successivo di a, che viene stampato sulla console perché non è interessato.

Che cosa si può fare è colpire una variabile con questo valore:

>>> a = iter(list(range(10))) 
>>> for i in a: 
... print(i) 
... b=next(a) 
... 
0 
2 
4 
6 
8 
6

trovo le risposte esistenti un po 'di confusione, perché solo indirettamente indicano la cosa mistificante essenziale nel codice di esempio: sia * "print i" e "next (a)" causano la stampa dei risultati.

Poiché stanno stampando elementi alternati della sequenza originale ed è imprevisto che la "prossima (a)" istruzione stia stampando, sembra che l'istruzione "print i" stia stampando tutti i valori.

In questa luce, diventa più chiaro che assegnando il risultato di "next (a)" a una variabile inibisce la stampa del suo risultato, in modo che solo i valori alternativi che la variabile loop 'i' vengono stampati. Allo stesso modo, rendere la dichiarazione "stampa" emette qualcosa di più distintivo disambigua anche.

(Una delle risposte esistenti smentisce gli altri perché quella risposta sta avendo il codice di esempio valutato come un blocco, in modo che l'interprete non sta segnalando i valori intermedi per "il prossimo (a)".)

Il La cosa seducente nel rispondere alle domande, in generale, è esplicita su ciò che è ovvio una volta che conosci la risposta. Può essere elusivo. Allo stesso modo, critica le risposte una volta che le capisci. E 'interessante ...

1

Si comporta nel modo desiderato, se chiamato in funzione:

>>> def test(): 
...  a = iter(list(range(10))) 
...  for i in a: 
...   print(i) 
...   next(a) 
... 
>>> test() 
0 
2 
4 
6 
8