Bon, je me suis décidé à chercher ce "local variable reference before assignment" et j'ai trouvé que lorsqu'on affecte une variable dans une méthode, par défaut elle est locale, il faut donc spécifier "global variable" avant. Pour moi c'est encore une mauvaise surprises avec Python : la fonction qui est "return somme" accède bien à la variable globale somme, mais la fonction qui est "somme = 1" crée une nouvelle variable locale somme. Ce n'est pas logique... Si on a besoin de mettre global somme en tête d'une fonction pour manipuler la variable globale, il faut que l'on doive le faire dans les deux situations, pas une seule. Que penses-tu de ce problème ?
Donc, bref, j'ai écrit le bout de code que j'ai spécifié plus haut (tu me demandes de te proposer du code à écrire en Python mais tu ne l'as toujours pas écrit, tu le noteras), sans utiliser globals() grâce à ton "trick" de passer par des fonctions getter/setter :
liste = [ 1, 2, 3 ]
somme = 0
def getSomme():
return somme
def setSomme(x):
global somme
somme = x
nouvelle_liste = map(lambda x, g=getSomme, s=setSomme : s(g()+x) or x*2, liste)
Bon, donc ok de cette manière on arrive à faire une closure, mais que d'efforts ! Et une fonction anonyme qui demande la définition de deux fonctions par variable extérieure à manipuler, hum...
Pour répondre à ta question sur l'utilité des closure : d'une part, quand tu l'as dans le langage que tu utilises (perl, ruby, ocaml par exemple) tu as plus tendance à l'utiliser, ça ne me semble pas choquant que tu aies l'impression de ne pas en avoir l'utilisation. Dans la même veine que le calcul de la somme ci-dessus, qui te demande en Python un deuxième parcours de la liste pour calculer la somme comme tu l'as écrit avec sum(liste), on peut en avoir besoin lorsqu'on a besoin de calculer quelque chose d'autre de non trivial (pour lequel il n'existe pas une fonction déjà définir comme sum) en même temps que le parcours de la liste, ou bien lorsque le parcours de cette liste est très coûteux, ou bien encore lorsqu'il provoque un effet de bord qui oblige à ne la parcourir qu'une seule fois. Un autre exemple courant est le branchement d'un callback sur un événement : typiquement dans gtk, par exemple avec le code suivant :
sub run_my_dialog() {
my $results = 1;
my $dialog = make_gtk_dialog();
$dialog->button1()->signal_connect(clicked => sub { $results = 2 })
$dialog->run();
return $results;
}
La possibilité d'écrire une fonction anonyme qui soit une closure est ici particulièrement pratique pour "sauver" une valeur qui sera disponible lorsque le dialogue sera fermé. Sans closure, écrire cette fonction devient beaucoup plus lourd (tu peux l'écrire en Python ?).
Sinon, au sujet des expressions ternaires, je m'en mords les c*** de ne pas m'en être servi pour ma critique de Python :) c'est vrai que c'est dommage d'avoir oublié ça (comme il est dommage de ne pas avoir mis "variable++" en Python ou en Ruby d'ailleurs) même si on s'adapte aux petites erreurs de son langage favori.
Alors pour terminer ce thread trop long sur une note plus positiive : je suis bien sûr d'accord que chaque langage a ses défauts : en Perl, l'objet est mal branlé, les $/@/% pour les types de données sans possibilité de nester c'est chiant, les prototypes des fonctions qui n'en sont pas vraiment et la nécessité d'affecter à la main les paramètres des fonctions dans des variables locales c'est naze, et j'en passe probablement beaucoup ; en Python on a quelques soucis comme déjà énumérés ; et en Ruby il y a aussi son lot de frustration, mais on ne va pas commencer avec ça. Ce thread a beaucoup dérivé lorsque tu m'as demandé si j'étais pas "tenté" par Python, mais je voudrais repréciser mon propos initial : je voulais montrer que pour les petits one-liner, les programmes très compacts et "jetables", Python n'est pas adapté ; je pense que les fonctionnalités de Python en font un langage adapté pour les "vrais" programmes plutôt que les one-liner (ce que tu disais toi-même plus haut il me semble) (même si je ne vois que des avantages à Ruby sur Python pour faire ce genre de programmes), je voulais donc dire que pour le genre de tâche que j'exposais au début, Python ne me semble pas adapté, et même si l'on aime Python pour plein de raisons, peut-être est-ce judicieux d'utiliser quelque chose d'autre - ce que disait un des commentaires du début, même si utiliser sed quand on a perl sous la main me semble relever du masochisme :).
[^] # 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.
Donc, bref, j'ai écrit le bout de code que j'ai spécifié plus haut (tu me demandes de te proposer du code à écrire en Python mais tu ne l'as toujours pas écrit, tu le noteras), sans utiliser globals() grâce à ton "trick" de passer par des fonctions getter/setter :
liste = [ 1, 2, 3 ]
somme = 0
def getSomme():
return somme
def setSomme(x):
global somme
somme = x
nouvelle_liste = map(lambda x, g=getSomme, s=setSomme : s(g()+x) or x*2, liste)
Bon, donc ok de cette manière on arrive à faire une closure, mais que d'efforts ! Et une fonction anonyme qui demande la définition de deux fonctions par variable extérieure à manipuler, hum...
Pour répondre à ta question sur l'utilité des closure : d'une part, quand tu l'as dans le langage que tu utilises (perl, ruby, ocaml par exemple) tu as plus tendance à l'utiliser, ça ne me semble pas choquant que tu aies l'impression de ne pas en avoir l'utilisation. Dans la même veine que le calcul de la somme ci-dessus, qui te demande en Python un deuxième parcours de la liste pour calculer la somme comme tu l'as écrit avec sum(liste), on peut en avoir besoin lorsqu'on a besoin de calculer quelque chose d'autre de non trivial (pour lequel il n'existe pas une fonction déjà définir comme sum) en même temps que le parcours de la liste, ou bien lorsque le parcours de cette liste est très coûteux, ou bien encore lorsqu'il provoque un effet de bord qui oblige à ne la parcourir qu'une seule fois. Un autre exemple courant est le branchement d'un callback sur un événement : typiquement dans gtk, par exemple avec le code suivant :
sub run_my_dialog() {
my $results = 1;
my $dialog = make_gtk_dialog();
$dialog->button1()->signal_connect(clicked => sub { $results = 2 })
$dialog->run();
return $results;
}
La possibilité d'écrire une fonction anonyme qui soit une closure est ici particulièrement pratique pour "sauver" une valeur qui sera disponible lorsque le dialogue sera fermé. Sans closure, écrire cette fonction devient beaucoup plus lourd (tu peux l'écrire en Python ?).
Sinon, au sujet des expressions ternaires, je m'en mords les c*** de ne pas m'en être servi pour ma critique de Python :) c'est vrai que c'est dommage d'avoir oublié ça (comme il est dommage de ne pas avoir mis "variable++" en Python ou en Ruby d'ailleurs) même si on s'adapte aux petites erreurs de son langage favori.
Alors pour terminer ce thread trop long sur une note plus positiive : je suis bien sûr d'accord que chaque langage a ses défauts : en Perl, l'objet est mal branlé, les $/@/% pour les types de données sans possibilité de nester c'est chiant, les prototypes des fonctions qui n'en sont pas vraiment et la nécessité d'affecter à la main les paramètres des fonctions dans des variables locales c'est naze, et j'en passe probablement beaucoup ; en Python on a quelques soucis comme déjà énumérés ; et en Ruby il y a aussi son lot de frustration, mais on ne va pas commencer avec ça. Ce thread a beaucoup dérivé lorsque tu m'as demandé si j'étais pas "tenté" par Python, mais je voudrais repréciser mon propos initial : je voulais montrer que pour les petits one-liner, les programmes très compacts et "jetables", Python n'est pas adapté ; je pense que les fonctionnalités de Python en font un langage adapté pour les "vrais" programmes plutôt que les one-liner (ce que tu disais toi-même plus haut il me semble) (même si je ne vois que des avantages à Ruby sur Python pour faire ce genre de programmes), je voulais donc dire que pour le genre de tâche que j'exposais au début, Python ne me semble pas adapté, et même si l'on aime Python pour plein de raisons, peut-être est-ce judicieux d'utiliser quelque chose d'autre - ce que disait un des commentaires du début, même si utiliser sed quand on a perl sous la main me semble relever du masochisme :).