in Python 2 di lista 'fughe' le variabili da portata esterna:
>>> [i for i in xrange(3)]
[0, 1, 2]
>>> i
2
notare che il comportamento è diverso su Python 3:
>>> [i for i in range(3)]
[0, 1, 2]
>>> i
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'i' is not defined
Quando si definisce lambda è destinato alla variabile i
, non il suo valore corrente come mostra il tuo secondo esempio. Ora, quando si assegna al nuovo valore i
lambda restituirà tutto ciò che è il valore corrente:
>>> a = [lambda: i for i in range(5)]
>>> a[0]()
4
>>> i = 'foobar'
>>> a[0]()
'foobar'
Poiché il valore della i
all'interno del loop è la lambda per sé si otterrà come valore di ritorno:
>>> i = a[0]
>>> i()
<function <lambda> at 0x01D689F0>
>>> i()()()()
<function <lambda> at 0x01D689F0>
UPDATE: Esempio su Python 2.7:
Python 2.7.6 (default, Jun 22 2015, 17:58:13)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> a = [lambda: i for i in range(5)]
>>> for i in a:
... print i()
...
<function <lambda> at 0x7f1eae7f15f0>
<function <lambda> at 0x7f1eae7f1668>
<function <lambda> at 0x7f1eae7f16e0>
<function <lambda> at 0x7f1eae7f1758>
<function <lambda> at 0x7f1eae7f17d0>
Same su Python 3.4:
Python 3.4.3 (default, Oct 14 2015, 20:28:29)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> a = [lambda: i for i in range(5)]
>>> for i in a:
... print(i())
...
4
4
4
4
4
Per i dettagli relativi alla variazione per quanto riguarda la portata variabile di lista vedere Guido blogpost from 2010.
Abbiamo anche apportato un altro cambiamento in Python 3, per migliorare l'equivalenza tra le list comprehensions e le espressioni del generatore. In Python 2, la lista di comprensione "perde" la variabile di controllo del ciclo nel perimetro circostante:
x = 'before'
a = [x for x in 1, 2, 3]
print x # this prints '3', not 'before'
Tuttavia, in Python 3, abbiamo deciso di risolvere il "piccolo sporco segreto" della list comprehension da utilizzando la stessa strategia di implementazione delle espressioni del generatore. Quindi, in Python 3, l'esempio sopra (dopo la modifica per usare print (x) :-) stamperà 'before', dimostrando che la 'x' nella comprensione delle liste temporaneamente ombreggia ma non sovrascrive la 'x' nell'ambiente circostante scopo.
Scusate per la chiusura, ho letto male la domanda. –
Whoops, mi dispiace per la segnalazione. Ho letto male anche io! –
Ho cambiato il titolo perché era * veramente * facile sfogliare la tua domanda e penso che tu avessi un semplice problema di binding tardivo invece di un problema relativo al riutilizzo del nome della variabile. (Ciò è evidenziato nelle chiusure e risposte errate). Il nuovo titolo richiama l'attenzione sul vero problema che ti preoccupa. Se vuoi riformularlo da quello che ho realizzato, assicurati di mantenere questo aspetto. – jpmc26