enumerate () - ing un generatore in Python


90

Mi piacerebbe sapere cosa succede quando passo il risultato di una funzione di generatore a enumerate () di python. Esempio:

def veryBigHello():
    i = 0
    while i < 10000000:
        i += 1
        yield "hello"

numbered = enumerate(veryBigHello())
for i, word in numbered:
    print i, word

L'enumerazione viene ripetuta pigramente o inghiotte tutto nel primo? Sono sicuro al 99,999% che sia pigro, quindi posso trattarlo esattamente come la funzione del generatore o devo fare attenzione a qualcosa?


1
Presumo che intendi incrementare i in veryBigHello.
robert

@robert: se non sbaglio i viene automaticamente aumentato
the_drow

@ the_drow Non nella veryBigHellofunzione stessa.
Will McCutchen

1
@ Will: Oh, corretto. Ma questo è solo pignolo. È un esempio. Risolto comunque.
the_drow

Risposte:


108

È pigro. È abbastanza facile dimostrare che è così:

>>> def abc():
...     letters = ['a','b','c']
...     for letter in letters:
...         print letter
...         yield letter
...
>>> numbered = enumerate(abc())
>>> for i, word in numbered:
...     print i, word
...
a
0 a
b
1 b
c
2 c

Questo è Python 2 o 3 (o entrambi)? È pigro in entrambi? Ho provato su Python 2 ed è pigro.
Becko

2
L'ho testato su Python 3.5.2 e valuta pigramente.
gobernador

42

È ancora più facile da dire rispetto a uno dei suggerimenti precedenti:

$ python
Python 2.5.5 (r255:77872, Mar 15 2010, 00:43:13)
[GCC 4.3.4 20090804 (release) 1] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> abc = (letter for letter in 'abc')
>>> abc
<generator object at 0x7ff29d8c>
>>> numbered = enumerate(abc)
>>> numbered
<enumerate object at 0x7ff29e2c>

Se enumerate non eseguisse una valutazione lenta, restituirebbe [(0,'a'), (1,'b'), (2,'c')]o qualcosa di (quasi) equivalente.

Ovviamente, enumerate è solo un generatore di fantasia:

def myenumerate(iterable):
   count = 0
   for _ in iterable:
      yield (count, _)
      count += 1

for i, val in myenumerate((letter for letter in 'abc')):
    print i, val

2
Grazie per questa spiegazione. Ho avuto un po 'di difficoltà a capire la risposta accettata. Almeno finché non ho visto il tuo.
trendsetter37

13

Dal momento che puoi chiamare questa funzione senza uscire dalla memoria eccezioni, è sicuramente pigro

def veryBigHello():
    i = 0
    while i < 1000000000000000000000000000:
        yield "hello"

numbered = enumerate(veryBigHello())
for i, word in numbered:
    print i, word

0

Alternativa alla vecchia scuola poiché stavo usando un generatore che qualcun altro (sklearn) ha scritto che non funzionava con gli approcci qui.

i=(-1)
for x in some_generator:
    i+=1
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.