Euh ton code me donne deux fois [5, 5, 5] (Python 2.3.4) - puisque le lambda capture encore une fois la valeur de la fonction à sa création (s1 donc) et ton affectation de s2 à somme n'y change donc rien (tu as testé ton code ?). Mais ça me semble une bonne idée que je vais continuer :
Qui me donne bien [5, 5, 5] et [7, 7, 7], puisque la valeur capturée est la fonction s1 qui elle capture bien la variable somme en tant que telle et non sa valeur, une fois appelée elle saura rendre la vraie valeur de somme.
Il est donc possible de "simuler" une closure en Python en définissant un getter pour la variable que l'on veut capturer - je ne m'en étais pas douté, cette discussion aura au moins l'avantage de me révéler ça :). J'aurais supposé qu'en changeant la valeur de somme depuis la fonction s1 j'aurais même pu réaliser le fameux truc qui nous occupe (changer une variable locale/globale depuis un lambda sans avoir recours à global()) mais Python me dit "local variable 'somme' referenced before assignment". Il veut bien que j'affecte x à somme mais pas que j'ajoute x à somme, ça doit être un truc commun en Python mais là je vois pas, tu sauras sûrement pourquoi.
Bon, c'est déjà ça - mais si on souhaite simuler des closure comme cela en Python on ne peut pas franchement dire que ce soit d'une élégance folle, tu ne trouves pas ? On se retrouve quand même avec trois "noms" différents pour une même variable : son vrai nom, le nom de son wrapper, et son nom affecté en paramètre du lambda...
[^] # Re: Bof...
Posté par gc . En réponse au message de la puissance de (beep) pour trouver un truc simple en 2 minutes. Évalué à 2.
liste = [ 1, 2, 3 ]
somme = 5
def s1(): return somme
l = lambda x, s=s1 : s()
print map(l, liste)
somme = 7
print map(l, liste)
Qui me donne bien [5, 5, 5] et [7, 7, 7], puisque la valeur capturée est la fonction s1 qui elle capture bien la variable somme en tant que telle et non sa valeur, une fois appelée elle saura rendre la vraie valeur de somme.
Il est donc possible de "simuler" une closure en Python en définissant un getter pour la variable que l'on veut capturer - je ne m'en étais pas douté, cette discussion aura au moins l'avantage de me révéler ça :). J'aurais supposé qu'en changeant la valeur de somme depuis la fonction s1 j'aurais même pu réaliser le fameux truc qui nous occupe (changer une variable locale/globale depuis un lambda sans avoir recours à global()) mais Python me dit "local variable 'somme' referenced before assignment". Il veut bien que j'affecte x à somme mais pas que j'ajoute x à somme, ça doit être un truc commun en Python mais là je vois pas, tu sauras sûrement pourquoi.
Bon, c'est déjà ça - mais si on souhaite simuler des closure comme cela en Python on ne peut pas franchement dire que ce soit d'une élégance folle, tu ne trouves pas ? On se retrouve quand même avec trois "noms" différents pour une même variable : son vrai nom, le nom de son wrapper, et son nom affecté en paramètre du lambda...