Comments on: Qu’est-ce qu’une closure en Python et Javascript ? http://sametmax.com/closure-en-python-et-javascript/ Deux développeurs en vadrouille qui se sortent les doigts du code Wed, 05 Feb 2014 12:15:31 +0000 hourly 1 http://wordpress.org/?v=3.3.1 By: Sam http://sametmax.com/closure-en-python-et-javascript/#comment-11741 Sam Sun, 28 Jul 2013 16:10:24 +0000 http://sametmax.com/?p=561#comment-11741 Effectivement, j'ai tort. Il va falloir que je mette à jour cet article. Effectivement, j’ai tort. Il va falloir que je mette à jour cet article.

]]>
By: outsmirkable http://sametmax.com/closure-en-python-et-javascript/#comment-11740 outsmirkable Sun, 28 Jul 2013 16:07:56 +0000 http://sametmax.com/?p=561#comment-11740 Cher Sam, Dans l'esprit « d'apprendre à un homme à pêcher », voici quelques commandes que vous pouvez taper sur votre console Python, je pense que ça vous éclaircira. Commençons par déclarer une variable : <code><pre lang="python"> »»» x = 5</pre></code> Et maintenant une fonction l'utilisant : <code><pre lang="python"> »»» def f(): . print x</pre></code> Quand nous faisons appel à f(), elle se « souvient » de x, même si x a été déclaré en-dehors de son scope. <code><pre lang="python"> »»» f() 5</pre></code> Jusqu'ici, tout va bien... Soyons fous, créons une deuxième fonction ! <code><pre lang="python"> »»» def g(): . print x + 1 »»» »»» g() 6</pre></code> Youpi, g() se "souvient" aussi de x ! Essayons de changer x. <code><pre lang="python"> »»» x = 10 »»» f() 10 »»» g() 11</pre></code> f() et g() ont pris en compte la nouvelle valeur. Euh... on parlait pas de valeurs « piégées » ? C'est vraiment ça une closure ? Hmm... il n'y a pas d'objet __closure__ dans f, ni dans g... <code><pre lang="python"> »»» f().__closure__ »»» »»» g().__closure__ »»»</pre></code> Que se passe-t-il si on efface la variable x ? <code><pre lang="python"> »»» del x »»» x Traceback (most recent call last): File "", line 1, in NameError: name 'x' is not defined »»»</pre></code> Ok, x n'est plus disponible, mais est-ce que f s'en souvient quand même ? <code><pre lang="python"> »»» f() Traceback (most recent call last): File "", line 1, in File "", line 2, in f NameError: global name 'x' is not defined</pre></code> Ah... bah non en fait. En plus Python nous parle d'un « global name 'x' » ? Il cherche une variable globale appelée x ? Je croyais que c'était seulement si je la déclarais "global x" ?!??! Pouf, pouf... essayons donc comme ça : <code><pre lang="python"> »»» def generateur(y): . def cloture(): . print y . return cloture</pre></code> On va générer deux nouvelles fonctions, h et m, qui vont piéger des variables. <code><pre lang="python"> »»» z = 5 »»» h = generateur(z) »»» z = 10 »»» m = generateur(z) »»» h() 5 »»» m() 10</pre></code> Cool, j'ai deux fonctions très utiles (hem...) qui utilisent des valeurs que je n'ai pas besoin de leur passer en paramètre. Et f() a bien gardé la valeur 5, alors que j'ai changé la valeur de z entre-temps ! <strong>C'est bien, ça m'a l'air plus sécurisé... je ne voudrais pas que le comportement de ma fonction f change au bon vouloir des variables extérieures</strong> ! Il paraît que c'est pas bien. Et d'ailleurs même si je supprime la variable z, et mon générateur aussi : <code><pre lang="python"> »»» del z »»» del generateur »»» h() 5 »»» m() 10</pre></code> Waou, mes deux fonctions marchent toujours, ce sont des vraies fermetures ! On le voit bien d'ailleurs : <code><pre lang="python"> »»» h.__closure__ (,)</pre></code> Pour finir : http://fr.wikipedia.org/wiki/Fermeture_%28informatique%29 Cher Sam,

Dans l’esprit « d’apprendre à un homme à pêcher », voici quelques commandes que vous pouvez taper sur votre console Python, je pense que ça vous éclaircira.

Commençons par déclarer une variable :

»»» x = 5


Et maintenant une fonction l’utilisant :

»»» def f():
.       print x


Quand nous faisons appel à f(), elle se « souvient » de x, même si x a été déclaré en-dehors de son scope.

»»» f()
5


Jusqu’ici, tout va bien… Soyons fous, créons une deuxième fonction !

»»» def g():
.       print x + 1
»»»
»»» g()
6


Youpi, g() se “souvient” aussi de x ! Essayons de changer x.

»»» x = 10
»»» f()
10
»»» g()
11


f() et g() ont pris en compte la nouvelle valeur. Euh… on parlait pas de valeurs « piégées » ? C’est vraiment ça une closure ? Hmm… il n’y a pas d’objet __closure__ dans f, ni dans g…

»»» f().__closure__
»»»
»»» g().__closure__
»»»


Que se passe-t-il si on efface la variable x ?

»»» del x
»»» x
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'x' is not defined
»»»


Ok, x n’est plus disponible, mais est-ce que f s’en souvient quand même ?

»»» f()
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 2, in f
NameError: global name 'x' is not defined


Ah… bah non en fait. En plus Python nous parle d’un « global name ‘x’ » ? Il cherche une variable globale appelée x ? Je croyais que c’était seulement si je la déclarais “global x” ?!??!

Pouf, pouf… essayons donc comme ça :

»»» def generateur(y):
.       def cloture():
.           print y
.       return cloture


On va générer deux nouvelles fonctions, h et m, qui vont piéger des variables.

»»» z = 5
»»» h = generateur(z)
»»» z = 10
»»» m = generateur(z)
»»» h()
5
»»» m()
10


Cool, j’ai deux fonctions très utiles (hem…) qui utilisent des valeurs que je n’ai pas besoin de leur passer en paramètre. Et f() a bien gardé la valeur 5, alors que j’ai changé la valeur de z entre-temps ! C’est bien, ça m’a l’air plus sécurisé… je ne voudrais pas que le comportement de ma fonction f change au bon vouloir des variables extérieures ! Il paraît que c’est pas bien. Et d’ailleurs même si je supprime la variable z, et mon générateur aussi :

»»» del z
»»» del generateur
»»» h()
5
»»» m()
10


Waou, mes deux fonctions marchent toujours, ce sont des vraies fermetures ! On le voit bien d’ailleurs :

»»» h.__closure__
(,)

Pour finir : http://fr.wikipedia.org/wiki/Fermeture_%28informatique%29

]]>
By: Sam http://sametmax.com/closure-en-python-et-javascript/#comment-11730 Sam Sun, 28 Jul 2013 09:00:56 +0000 http://sametmax.com/?p=561#comment-11730 Cher ami, une variable ne peut être globale que si elle est déclarée avec le mot clé global en Python, ou si elle n'est pas déclarée avec var en javascript. Ce n'est pas le cas dans l'article. La closure est un espace de mémoire reservé sous certaines conditions. Elle peut se faire dans le cadre de ton exemple - un retour de fonction - mais ce n'est pas le seul cas. On retrouve des closures dans tout un tas de blocs, dans différentes langages. Cher ami, une variable ne peut être globale que si elle est déclarée avec le mot clé global en Python, ou si elle n’est pas déclarée avec var en javascript. Ce n’est pas le cas dans l’article.

La closure est un espace de mémoire reservé sous certaines conditions. Elle peut se faire dans le cadre de ton exemple – un retour de fonction – mais ce n’est pas le seul cas. On retrouve des closures dans tout un tas de blocs, dans différentes langages.

]]>
By: outsmirkable http://sametmax.com/closure-en-python-et-javascript/#comment-11729 outsmirkable Sun, 28 Jul 2013 08:47:39 +0000 http://sametmax.com/?p=561#comment-11729 Cet article est complètement faux. Il y a confusion entre variable globale et <em>closure</em>. <strong>Une <em>closure</em> n'est pas une variable, c'est une FONCTION</strong>. En fait, créer une <em>closure</em> implique d'avoir une fonction qui retourne une fonction (la <em>closure</em>). Voici un exemple simple à retenir : <code><pre lang="python"> »» def generer_closure(piegee): . def closure(x): . # Faire une opération avec la variable piégée . return piegee ** x . return closure »» # On génère une fonction qui "piège" la valeur 10 »» f = generer_closure(10) »» f(3) 1000 »» # La fonction f se "souvient" de la valeur 10 ! »» # On peut même supprimer le générateur »» del generer_closure »» f(2) 100 »» # Et ça marche toujours ! »» # En fait notre fonction possède un attribut caché »» # Voilà où se cache la valeur piégée »» f.__closure__[0].cell_contents 10 </pre> </code> Il arrive qu'on ait besoin d'écrire une méthode pour laquelle une partie des arguments ne change jamais. On est alors souvent tenté d'utiliser des variables globales pour ces valeurs "fixes". <strong>Le but des <em>closures</em> est justement d'éviter de déclarer des variables globales</strong>, tout en obtenant une méthode agréable à utiliser, qui "connait" les valeurs fixes qu'elle doit utiliser. Cet article est complètement faux. Il y a confusion entre variable globale et closure. Une closure n’est pas une variable, c’est une FONCTION. En fait, créer une closure implique d’avoir une fonction qui retourne une fonction (la closure). Voici un exemple simple à retenir :

»» def generer_closure(piegee):
.       def closure(x):
.            # Faire une opération avec la variable piégée
.            return piegee ** x
.       return closure
 
»» # On génère une fonction qui "piège" la valeur 10
»» f = generer_closure(10)
»» f(3)
1000
»» # La fonction f se "souvient" de la valeur 10 !
»» # On peut même supprimer le générateur
»» del generer_closure
»» f(2)
100
»» # Et ça marche toujours !
»» # En fait notre fonction possède un attribut caché
»» # Voilà où se cache la valeur piégée
»» f.__closure__[0].cell_contents
10

Il arrive qu’on ait besoin d’écrire une méthode pour laquelle une partie des arguments ne change jamais. On est alors souvent tenté d’utiliser des variables globales pour ces valeurs “fixes”. Le but des closures est justement d’éviter de déclarer des variables globales, tout en obtenant une méthode agréable à utiliser, qui “connait” les valeurs fixes qu’elle doit utiliser.

]]>
By: Sam http://sametmax.com/closure-en-python-et-javascript/#comment-604 Sam Tue, 10 Jul 2012 17:18:28 +0000 http://sametmax.com/?p=561#comment-604 @JM: pas exactement. <code>global</code> permet de modifier une variable comme si c'était une variable globale. Il y a des effets de bords possibles (ce qui est un des gros défaut de Javascript) car une variable de tel nom peut exister à la racine du fichier. Une solution plus propre est d'utiliser le mot clé <code>nonlocal</code>, qui permet de considérer une variable comme étant celle du scope du dessus <strong>le plus proche</strong>. On évite ainsi de modifier en cascade Mais <code>nonlocal</code> n'existe qu'à partir de Python 3 que personne n'utilise en production. Merci pour les corrections :-) Plus un article est propre, plus il est agréable à lire. Surtout n'hésitez pas à faire le grammar nazi en commentaire, ce sera toujours bien acceuilli. @JM: pas exactement.

global permet de modifier une variable comme si c’était une variable globale. Il y a des effets de bords possibles (ce qui est un des gros défaut de Javascript) car une variable de tel nom peut exister à la racine du fichier.

Une solution plus propre est d’utiliser le mot clé nonlocal, qui permet de considérer une variable comme étant celle du scope du dessus le plus proche. On évite ainsi de modifier en cascade

Mais nonlocal n’existe qu’à partir de Python 3 que personne n’utilise en production.

Merci pour les corrections :-) Plus un article est propre, plus il est agréable à lire. Surtout n’hésitez pas à faire le grammar nazi en commentaire, ce sera toujours bien acceuilli.

]]>
By: JM http://sametmax.com/closure-en-python-et-javascript/#comment-585 JM Tue, 03 Jul 2012 13:39:22 +0000 http://sametmax.com/?p=561#comment-585 À noter que pour modifier une variable à l'extérieur du scope de la fonction, on peut utiliser le mot de clé <strong>global</strong> qui permet d'avoir le même comportement qu'en Javascript. Encore moi pour la grammaire (supprime cette partie du commentaire, mais peut-être que c'est cool de laisser la partie ci-dessus.) Les closure (+s) on définie (t) ai (+t) été changé. ne créé pas de closure. (crée) À noter que pour modifier une variable à l’extérieur du scope de la fonction, on peut utiliser le mot de clé global qui permet d’avoir le même comportement qu’en Javascript.

Encore moi pour la grammaire (supprime cette partie du commentaire, mais peut-être que c’est cool de laisser la partie ci-dessus.)

Les closure (+s)
on définie (t)
ai (+t) été changé.
ne créé pas de closure. (crée)

]]>