2012-06-12 18 views
5

Sia l'elenco che gli oggetti islice sono iterabili, ma perché questa differenza nel risultato.funzione tee dalla libreria itertools

r = [1, 2, 3, 4]    
i1, i2 = tee(r) 
print [e for e in r if e < 3] 
print [e for e in i2] 
#[1, 2] 
#[1, 2, 3, 4] 


r = islice(count(), 1, 5)   
i1, i2 = tee(r) 
print [e for e in r if e < 3] 
print [e for e in i2] 
#[1, 2] 
#[] 

risposta

14

Il problema qui è che tee() ha bisogno di consumare i valori dal iteratore originale, se si inizia a consumarle dal iteratore originale, sarà in grado di funzionare correttamente. Nell'esempio del tuo elenco, l'iterazione ricomincia semplicemente. Nell'esempio del generatore, è esaurito e non vengono prodotti più valori.

Questo è ben documentato:

Una volta tee() ha fatto una scissione, l'originale iterabile non deve essere utilizzato in qualsiasi altro luogo; altrimenti, l'iterabile potrebbe avanzare senza che gli oggetti t siano informati.

Source

Modifica per illustrare il punto nella differenza tra una lista e un generatore:

>>> from itertools import islice, count 
>>> a = list(range(5)) 
>>> b = islice(count(), 0, 5) 
>>> a 
[0, 1, 2, 3, 4] 
>>> b 
<itertools.islice object at 0x7fabc95d0fc8> 
>>> for item in a: 
...  print(item) 
... 
0 
1 
2 
3 
4 
>>> for item in a: 
...  print(item) 
... 
0 
1 
2 
3 
4 
>>> for item in b: 
...  print(item) 
... 
0 
1 
2 
3 
4 
>>> for item in b: 
...  print(item) 
... 
>>> 
+0

ma l'oggetto elenco e l'oggetto islice devono comportarsi allo stesso modo, giusto? – John

+1

@John No, quando esegui il ciclo sull'elenco, ottieni un nuovo iteratore ogni volta, il che significa che ottieni comunque i valori. Quando si usa 'islice()' si ottiene un generatore, che produrrà i valori una volta e quindi sarà esaurito. Provalo tu stesso: basta ripetere il ciclo su una lista due volte, quindi eseguire un'islice e ripetere l'operazione due volte - notare la differenza di comportamento. –

+0

@John Per far sì che i due esempi si comportino allo stesso modo, usate 'r = iter ([1,2,3,4])' piuttosto che 'r = [1,2,3,4]'. – clacke

0

nella lista tue comprehensions, si desidera sostituire r con i1.