Evaluation économique des éléments d'une séquence

Le
Pierre Maurette
(supersedes <mn.b2a67d983309c72d.79899@wanadoo.fr>)

Bonjour,

et désolé si je réveille quelqu'un. Déjà la date, mais en plus le
week-end, pas sûr que mes interrogations trouvent la moindre oreille.

En l'absence de switchcase, j'ai pris l'habitude d'utiliser sans
doute trop souvent l'accès à une séquence, souvent un dictionnaire,
pour faire des choix. Au début, il s'agissait essentiellement d'un
petit package de gestion d'actions, réutilisé dans chacun de mes petits
programmes-outils. J'avais une version ligne de commandes (optparse) ou
inclusif un petit clickodrome prémâché (Tkinter) et ça débouchait sur
un dictionnaire de fonctions, lambda ou pas. En tout cas des objets
fonction, et ça ne me semble pas poser de problème, encore aujourd'hui.
Ensuite, j'ai abusé du dictionnaire. Au jeu "tout programme Python doit
tenir sur une ligne", j'ai ajouté le "je ne veux voir aucun if".

Je me suis récemment aperçu que j'en étais arrivé à écrire des trucs
immondes:

def FonctionVachementLongue():
print 'Dans FonctionVachementLongue()'
return 12

b = {
# 'boom' : 1/0
'boom' : 1
, 'deux' : 10 / 2
, 'poireau' : FonctionVachementLongue()
, 'oiseau' : {'clef' : (1.25, 'pigeon', 3 *
FonctionVachementLongue())}
, 'ahahah' : lambda x: 2 * x
}['ahahah']

print b, '', b(10)

<correction: la sortie>
Dans FonctionVachementLongue()
Dans FonctionVachementLongue()
<function <lambda> at 0x023D9AB0>
20
</correction>

Bien voir que le dictionnaire n'est plus utilisé, et d'ailleurs plus
utilisable, une fois que b est initialisé.

Il y a une façon mécanique de rattraper ça:

b = {
'boom' : lambda : 1 / 0
, 'deux' : lambda : 10 / 2
, 'poireau' : lambda : FonctionVachementLongue()
, 'oiseau' : lambda : {'clef' : (1.25, 'pigeon', 3 *
FonctionVachementLongue())}
, 'ahahah' : lambda : lambda x: 2 * x
}['ahahah']()

print b, '', b(10)

<correction: la sortie>
<function <lambda> at 0x023D9AB0>
20
</correction>

La première question est de savoir si cette rustine est correcte. Elle
me donne satisfaction, pour moi ça reste lisible, encore relativement
compact, et éditable facilement.

Les autres questions, de serait de savoir si ce truc est très connu et
utilisé, ou alors s'il existe une méthode native simple voire évidente
pour arriver au même résultat

Sur ce, bonne bronzette à tous

--
Pierre Maurette
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
yves
Le #19974821
Le Sat, 22 Aug 2009 11:45:31 +0200, Pierre Maurette a écrit:

Bonjour,

j'ai probablement tout compris de travers mais:

Bien voir que le dictionnaire n'est plus utilisé, et d'ailleurs plus
utilisable, une fois que b est initialisé.



C'est ça le problème ?

Quid de ça ?:
***********
def FVLongue():
print 'Dans FVLongue()'
return 12

d = {
# 'boom' : 1/0
'boom' : 1
, 'deux' : 10 / 2
, 'poireau' : FVLongue()
, 'oiseau' : {'clef' : (1.25,'pigeon', 3 * FVLongue())}
, 'ahahah' : lambda x: 2 * x
}

b = d['ahahah']
print b, 'n', b(10)
c = d['boom']
print c
b = d['deux']
print b
***********

@+
--
Yves
Pierre Maurette
Le #19975321
yves, le 23/08/2009 a écrit :
Le Sat, 22 Aug 2009 11:45:31 +0200, Pierre Maurette a écrit:

Bonjour,

j'ai probablement tout compris de travers mais:

Bien voir que le dictionnaire n'est plus utilisé, et d'ailleurs plus
utilisable, une fois que b est initialisé.



C'est ça le problème ?

Quid de ça ?:
***********
def FVLongue():
print 'Dans FVLongue()'
return 12

d = {
# 'boom' : 1/0
'boom' : 1
, 'deux' : 10 / 2
, 'poireau' : FVLongue()
, 'oiseau' : {'clef' : (1.25,'pigeon', 3 * FVLongue())}
, 'ahahah' : lambda x: 2 * x
}

b = d['ahahah']
print b, 'n', b(10)
c = d['boom']
print c
b = d['deux']
print b
***********



Merci d'avoir pris le temps de me lire, j'imagine que ce n'était pas
très clair ;-)

Non, ce n'est pas là qu'est le problème. Ce que je tentais d'expliquer,
c'est que je n'avais pas besoin du dictionnaire - ou plus généralement
de la séquence - mais uniquement d'un élément de cette séquence.
Typiquement c'est du code d'initialisation, qui par exemple dépend d'un
environnement donc également des arguments de la ligne de commande.

Le problème, c'est que si, dans votre code, vous effacez tout ce qui
est après la ligne:
b = d['ahahah']
ou même:
print b, 'n', b(10)
vous constaterez que FVLongue() est appelée deux fois, parce que
d['poireau'] et d['oiseau'] sont évaluées.

--
Pierre Maurette
Bruno Desthuilliers
Le #19978331
Pierre Maurette a écrit :
(snip)
Il y a une façon mécanique de rattraper ça:

b = {
'boom' : lambda : 1 / 0
, 'deux' : lambda : 10 / 2
, 'poireau' : lambda : FonctionVachementLongue()



Tu n'a pas besoin d'une lambda ici - une fonction est un obhjet comme un
autre, donc ceci suffit:

'poireau' : FonctionVachementLongue



, 'oiseau' : lambda : {'clef' : (1.25, 'pigeon', 3 *
FonctionVachementLongue())}
, 'ahahah' : lambda : lambda x: 2 * x
}['ahahah']()

print b, 'n', b(10)

<correction: la sortie>
<function <lambda> at 0x023D9AB0>
20
</correction>

La première question est de savoir si cette rustine est correcte. Elle
me donne satisfaction, pour moi ça reste lisible, encore relativement
compact, et éditable facilement.

Les autres questions, de serait de savoir si ce truc est très connu et
utilisé,



Utiliser un mapping cle:fonction pour le dispatch ? Oui, c'est un idiome
courant. Ceci étant, si c'est juste pour un code d'initialisation (comme
dans ton cas), c'est un peu overkill AMHA - à moins que tu n'ai besoin
de la flexibilité qu'apporte le dict (possibilité de passage du dict en
paramètre de fonction etc).

ou alors s'il existe une méthode native simple voire évidente
pour arriver au même résultat...



if / elif ?-)

Si tu n'a pas spécialement besoin de flexibilité à cet endroit là, une
série de conditionnelles sera certainement plus efficace. A toi de voir...
Pierre Maurette
Le #19978971
Bruno Desthuilliers, le 24/08/2009 a écrit :
Pierre Maurette a écrit :
(snip)
Il y a une façon mécanique de rattraper ça:

b = {
'boom' : lambda : 1 / 0
, 'deux' : lambda : 10 / 2
, 'poireau' : lambda : FonctionVachementLongue()



Tu n'a pas besoin d'une lambda ici - une fonction est un obhjet comme un
autre, donc ceci suffit:

'poireau' : FonctionVachementLongue



J'applique *mécaniquement* une modif ou une technique. Je ne pense pas
gagner à étudier les cas particuliers. Mon exemple est incomplet, mais
je dois envisager FonctionVachementLongue(arg). J'ai d'ailleurs souvent
le cas de la même fonction avec des arguments différents.

, 'oiseau' : lambda : {'clef' : (1.25, 'pigeon', 3 *
FonctionVachementLongue())}
, 'ahahah' : lambda : lambda x: 2 * x
}['ahahah']()

print b, 'n', b(10)

<correction: la sortie>
<function <lambda> at 0x023D9AB0>
20
</correction>

La première question est de savoir si cette rustine est correcte. Elle me
donne satisfaction, pour moi ça reste lisible, encore relativement compact,
et éditable facilement.

Les autres questions, de serait de savoir si ce truc est très connu et
utilisé,



Utiliser un mapping cle:fonction pour le dispatch ? Oui, c'est un idiome
courant. Ceci étant, si c'est juste pour un code d'initialisation (comme dans
ton cas), c'est un peu overkill AMHA - à moins que tu n'ai besoin de la
flexibilité qu'apporte le dict (possibilité de passage du dict en paramètre
de fonction etc).



Le cas que j'ai sous les yeux c'est un fichier SConstruct pour Scons.
Les clés sont dans ce genre: sys.platform + platform.uname()[1]

ou alors s'il existe une méthode native simple voire évidente pour arriver
au même résultat...



if / elif ?-)

Si tu n'a pas spécialement besoin de flexibilité à cet endroit là, une série
de conditionnelles sera certainement plus efficace. A toi de voir...



Comme je l'écrivais, j'abuse sans doute des séquences, jusqu'à me faire
piéger par cette histoire d'évaluations inutiles. En fait, j'ai une
idée - fausse certainement en Python - qui me vient d'autre langages et
qui voudrait qu'une section de code soit meilleure si elle ne contient
pas de branchement. Et en abusant des séquences, j'ai fini par trouver
ç très lisible. Le lambda supplémentaire ne devrait pas gêner, s'il est
systématique et en soignant la mise en page.

Je vous remercie de votre réponse, je vais réfléchir au problème pour
le futur.

--
Pierre Maurette
Publicité
Poster une réponse
Anonyme