title: Python : lisibilité vs simplicité slug: python-et-underscore date: 2006-04-25 21:54:36 type: post vignette: images/logos/python_nouveau.png contextual_title1: Bonnes pratiques et astuces Python contextual_url1: 20080511-bonnes-pratiques-et-astuces-python contextual_title2: Benchmarks map, filter vs. list-comprehensions contextual_url2: 20061025-benchmarks-map-filter-vs-list-comprehensions contextual_title3: Principales nouveautés dans Python 2.5 contextual_url3: 20060304-principales-nouveautes-dans-python-25

Le programmeur est fainéant. C'est ainsi. S'il ne l'était pas, il n'essayerait pas de s'aider d'un ordinateur. Du coup il évite dans la mesure du possible de s'encombrer de variables trop longues, ou d'appels répétitifs un peu trop élaborés. Heureusement, en Python, on peut simplifier tout ça. Mais la simplification peut mener à un manque de lisibilité dans certains cas. Un cas intéressant est celui de l'underscore.

La valeur précédente

Pas grand monde ne le sait mais testez de vous-même dans un shell :

>>> 8 + 2
10
>>> _
10

C'est très peu employé et ça rend le code très peu lisible, quitte a avoir une variable temporaire rappelant la dernière valeur autant qu'on comprenne de quoi il retourne. Surtout qu'il est possible d'attribuer d'autres fonctions à l'underscore.

Variable temporaire inutile

L'underscore est souvent utilisé pour créer des listes de liste :

>>> [[0] for _ in range(3)]
[[0], [0], [0]]

Vous vous demandez peut-être pourquoi ne pas faire un simple :

>>> [[0]] * 3

Tout simplement car ça crée des copies de listes et non des nouvelles listes donc si vous en modifiez une, ça se répercute sur les autres.

Il peut être aussi utilisé pour des fonctions renvoyant trop d'information, par exemple dans :

>>> jour, mois, _ = date_actuelle()

Si l'on ne veut pas s'encombrer de l'année (en supposant que le troisième argument renvoyé par la fonction est l'année bien sûr...).

Ces utilisations ponctuelles sont pratiques et ne nuisent pas trop à la lisibilité du code.

Traduction avec gettext

import gettext
gettext.bindtextdomain('myapplication', '/path/to/my/language/directory')
gettext.textdomain('myapplication')
_ = gettext.gettext
# ...
print _('This is a translatable string.')

Ça par contre c'est très employé, et oui les programmeurs sont des fainéants ;-). C'est pas forcément lisible et ça demande un peu d'habitude mais il faut reconnaître que c'est bien pratique et que c'est devenu usage courant donc autant l'utiliser.

Utilisation à la place de self

C'est souvent demandé à Guido sur la mailing-list python et il est assez intransigeant là-dessus (et je suis d'accord avec lui). Python est un langage simple et on doit pas tomber dans les gri-gri de Perl (désolé pour les mongeurs dans l'assistance...). Alors bien sûr vous pouvez utiliser n'importe quel mot-clé à la place de self pour vos classes et plus il est court moins vous aurez à taper de caractère ensuite mais self est un bon compromis, il est à la fois court et lisible. Pensez aux personnes qui vont devoir relire un jour votre code (il est très probable que ce soit vous et que vous ayez évolué !), autant se baser sur un formalisme commun (parce que ça commence comme ça puis on se met à utiliser * à la place de yield et on finit avec un code illisible...).

Python est un des langages les plus lisible mais aussi un des plus paramétrable (j'entend par là entièrement redéfinissable au niveau des mots-clé, des fonctions, etc...). Essayez de ne pas suivre des méthodes reconnues pour être la clé de votre engagement à vie dans votre boîte ;-).