10 trucs que je déteste en Python 28


Il faut savoir être honnête dans la vie, et puisque j’ai tapé sur le JS dans le dernier article, on va rappeler que rien n’est parfait et que chez les Pythoneux aussi y a du boulot.

Le piège des paramètres par défaut mutables

C’est le “ne pas faire” le plus connu en Python. Mais même en étant au courant on se fait TOUS baiser un jour.

def transfert(source, res=[]):
	# faire un truc qui passe des élement de
	# source à res

Ce code va remplir res d’appels en appels, qui ne sera donc plus une liste vide dès le second appel.

It’s a feature, not a bug, mais c’est pourtant rarement ce qu’on veut.

L’opérateur pour les tuples est la virgule, pas les parenthèses

C’est pratique car ça permet de rendre l’unpacking propre et élégant. Mais c’est aussi un coup à se tirer une balle dans le pied :

>>> t = ("a") # ceci n'est pas un tuple !
>>> type(t)
str
>>> t = "a", # grrrr
>>> type(t) 
tuple
>>> t = () 
>>> type(t) # WAIT WAT ?
tuple

Et comme les string sont itérables, la boucle for marchera toujours, silencieusement, jusqu’à ce que bug s’en suive.

Pas de set literal vide

On peut faire set(), on peut faire {1}, on peut faire () mais on ne peut pas faire {} puisque c’est un dico, ni {,} puisque c’est une syntax error. Ces deux lettres à taper en plus pèsent sur ma conscience.

Le packaging

Packager un programme Python est une grosse galère. Créer un setup.py est facile, mais savoir comment le créer, c’est une autre histoire. En fait le seul tuto valable sur la question est celui de ce blog, et il commence à être vieux. Vous savez pourquoi ? J’ai pas la foi de le mettre à jour car ça veut dire de nouveau passer des heures à me renseigner sur ce qu’il faut faire maintenant.

En fait un exe ou un deb devrait se faire en une ligne de commande.

Les modules inutiles de stdlib

Vous saviez qu’il y a un module pour lire les fichiers WAV dans la stdlib ? Sérieusement, qu’est-ce que ça fout dans la lib standard ?

La convention de langage, pas respectée dans la stdlib

Même après le nettoyage de Python 3, des libs existent qui utilisent le camelcase pour les noms de méthodes comme par exemple unittest. Le code de ces libs lui-même n’est pas PEP8, ce qui craint dès qu’on veut voir comment c’est fait à l’intérieur.

La concaténation automatique fonctionne à côté de l’opérateur virgules

J’adore le fait que :

("1"
"2")

Se concatène automatiquement.

Mais ça devrait lever une syntax error quand c’est déclaré à côté de virgules pour éviter cette merde :

var = (
"1",
"2"
"3"
)

Combien de fois je me suis fait niquer avec ça dans settings.py

On n’a pas accès au bloc de code dans un with

Il y a des tas de context managers géniaux qu’on pourrait faire si on avait accès au bloc de code exposée dans la close with comme on pourrait le faire avec lisp. Cette limitation m’a frustré plus d’une fois.

Pas de plug de code à chaud

Je rêve de cette feature.

Ecrire du code parallèle, concurrent ou non bloquant est lourd

Syntaxiquement c’est pas top, surtout qu’on doit contourner souvent le GIL. Une grosse amélioration pour l’io async arrive avec la 3.4 mais elle sera surtout bas niveau.

Y a pas de point 10

Ce langage est fantastique.

Ce qui n’est PAS un problème à mes yeux

Le passage à Python 3

A mon sens, brillament exécuté. Je sais que les gens pensent que ça prend un temps fou et que ça a foutu la merde, etc. Mais en vérité, c’est un des rares langages qui ait géré la transition aussi bien : largement documentée, outillée et suivie, bien soutenue par la communauté, avec tout le temps qu’il faut pour la transition mais une direction ferme de la part du BDFL. En plus il est POSSIBLE d’écrire du code qui fonctionne dans les deux versions alors qu’elles sont supposément incompatibles. C’est assez fou quand on y pense.

Il y a d’autres langages qui n’ont jamais réussi ce genre de changements, comme PERL (qui en est mort) ou PHP (qui a avorté).

Les espaces significatifs

Best. Feature. Ever.

Les lambdas sur une ligne

Ne pas toujours pouvoir faire des fonctions anonymes pour les callback, c’est un peu moins élégants, mais sinon, ça ne me manque pas.

L’encoding

Les gens râlent sur la gestion de l’encoding Python parce qu’ils ne comprennent pas ce qu’ils font. Mais personnellement je trouve excellent que le langage te force à gérer CORRECTEMENT tes encodings ou te lève une erreur. J’ai vu tellement de bases de données corrompues, de scripts qui affichent des hiéroglyphes, des “?” plein les pages Web, que je me dis que trop de personnes ignorent juste complètement la question. Et le jour où ça merde, ils passent un mois à réparer.

En 2.7, cette gestion était assez verbeuse par contre, et je suis bien content que ça change en 3.4.

28 thoughts on “10 trucs que je déteste en Python

  • pihito

    Venant du java, depuis quelques mois je découvre python. Personnellement ce qui le pose le plus d agacement c est le système d indentation. Mes devs ne sont pas fait sur le même os que la cible et je perd systématiquement quelques indent…

  • herison

    Salut

    Super :D J’avais jamais compris pourquoi pylint m’indiqué une erreur lorsque je fesais un def foo( a=1, b=[] )… Merci !

    @pihito
    Utilise des espaces à le place des tab. Ce qui va être chian entre les OS c’est de pacer à #-*- coding:utf-8 -*- sous linux et sous Windows c’est # -*- coding: iso-8859-1 -*- ou alors c’était Latin 1, Je me souvient plus.

    @ Sam
    C’est quoi les espaces significatifs et les lambdas sur une ligne ?

    @+

  • Gontran

    @pihito: D’un côté, il est de notoriété publique que les tab dans un code source est une hérésie.

    Sympa l’article sinon :)

  • Sam Post author

    @herison: les espaces significatifs, c’est l’indentation par espace ou tab justement. J’ai rajouté un lien vers l’article sur les lambdas.

  • maethor

    Dans le second exemple, un type(t) serait plus pertinant qu’un type("a"). Et ça montre qu’effectivement le résultat est un str, pas un tuple.

    J’vais avoir droit à un merci bibi ? :D

  • Réchèr

    +10000 pour la transformation en .exe qui n’est pas naturelle.

    Exemple rigolo : la librairie pygame est buggée. On peut transformer du code qui l’utilise si il est écrit en python 2.6, mais pas plus haut. Et si ça se trouve il y a plein d’autres exemples comme ça.

  • Swizz

    Le plus gros problème personnellement rencontré c’est quand je bosses en groupe et qu’il y en a un qui indente avec des espaces (mon cas) et d’autres avec des tabulations.

  • mothsART

    >>> t = ("a") # ceci n'est pas un tuple !
    >>> type("a")

    Je suppose que pour l’exemple, tu voulais plutôt :
    >>> type(t)

    Le passage à Pythnon Python 3

  • kontre

    Un truc sur lequel j’ai eu du mal au début c’est la borne finale des slices non inclue. Mais c’est qu’une question d’habitude au final.

    Par contre là où ça pèche beaucoup aujourd’hui c’est pour le code parallèle. Sans parler du GIL, le module multiprocessing a pas mal de limitations. Y’a tellement de multicœur aujourd’hui que c’est vraiment un gros désavantage.

    Ça, et le packaging…

  • Maxime

    Ce que je trouve dommage c’est que Python soit case sensitive. Ca n’apporte rien que des erreurs sournoises. Un heritage malheureux et inutile du C, sauf qu’en C les erreurs sont detectees par le compilateur.

  • kontre

    C’est super utile le case sensitive. Tu fais jamais ça toi:

    maclasse = MaClasse()

    Pour éviter les erreurs sournoises, tu as des outils genre pep8, pylint, pychecker… Et les tests unitaires, si t’as du temps devant toi.

  • herison

    @Sam

    les espaces significatifs, c’est l’indentation par espace ou tab justement. J’ai rajouté un lien vers l’article sur les lambdas.

    Merci, en fait, en lisant l’article la première fois je pensais que tu parlais de fonctionnalités apparu dans python 3, ça me semblais super obscure sachant que je conaissais déjà c’est truc dans python 2.0 ^^.

    J’ai déjà rencontré des personnes qui trouvent l’indentation par les espaces ridicule. C’est pourtant tellement génial de garder le code propre et d’évite les erreurs du genre:

    if ( truc )  {
        instr_1 ;
        instr_2 ;
    } else 
        chose  ;
        autre_chose ; // Raté ça fait pas ce que tu pense.

    Mais je pense que plus tu taff sur un seul langage et moins tu veux qu’on change tes habitudes à la fin tu trouve des programmeurs à l’espris vieux con qui bosse que sur un seul language est dans sa version 1999 parceque c’est comme ça qu’il l’on appris et tout le reste c’est de la merde. D’un autre coté il faut bien avouer qu’il existe quand même des langage bien plus merdique que d’autre et la différence apparaît avec la taille du projet.

    Un truc un peu lourd en python, c’est la rich comparaison ça va qu’il y à la class @total_ordering. Mais avoir juste les méthodes __cmp__ et __eq__ me semblait bien.

    Merci pour vos articles et votre site :-)

  • N.

    Du coup, le prochain article est sur le dernier point? La gestion de l’UTF-8 avant (2.7) et après (3.4): Bonnes pratiques et galères?

  • furankun

    Quelques typos encore:

    Et fait un exe ou un deb devrait… -> En fait un exe ou un deb devrait

    Les gens râles -> Les gens râlent

    hierogliphes -> hiéroglyphes

    De mon côté je continue à me battre avec les différences entre parenthèses, crochets et accolades (bien que pour ces dernières ça m’arrive rarement vu que c’est vraiment spécifique aux dicos), mais ça va venir. Saloperie de Numpy :D

  • kontre

    Halte là, on en dénigre pas numpy en ma présence ! :p
    Non, sérieux, avant python/numpy je faisais du matlab. En matlab, l’indexation et l’appel de fonction utilisent tous les deux des parenthèses, je vous raconte pas le bordel pour s’y retrouver dans les expressions, ou dans un code qu’on connait pas. Vivent les crochets !
    Y’a des tonnes de conteneurs en python, et même si ça fait peur aux débutants c’est un énorme point fort du langage. D’ailleurs les accolades sont utilisées aussi pour les sets, pas que pour les dicos. :)

  • Teocali

    Je pense qu’il parle de modifier le code d’un programme (typiquement, une application web) en cours d’execution. C’est sur que c’est un bonheur quand ca marche. La JVM java le permet plus ou moins en mode debug, mais c’est surtout avec JRebel que c’est assez genial : tu modifies une classe, tu la compiles, et poum ! Jrebel repercute automaitquement les modifications dans ton code. Que du bonheur ! Un PyRebel, ca serait le pied en ord massif…

  • Sam Post author

    @Mathieu: teocali a bien expliqué le truc. C’est quelque chose de formidable dans Erlang par exemple, tu ton process tourne, tu modifie ton code, et BAM, et ton process est modifié. Pas besoin de redémarer. C’est beau.

  • hindflo

    Le point 10 ça pourrait pas être le manque de documentation précise par rapport à d’autres langages (genre le java)?

    Par exemple pour tkinter (faisant partie des libs standard) la doc la plus complète que j’ai trouvé c’est celle là: http://effbot.org/tkinterbook/

    Et même là il y’a quand même plein d’argument non expliqués.
    Si on compare à la doc systématique du site d’oracle ça fait mal.

    Après je concède que c’est beaucoup plus difficile de faire une doc en python vus que les fonctions peuvent prendre un demis million de paramètres et qu’il n’y a pas de système pratique comme la javadoc (à ma connaissance).

    ps: qu’on soit bien d’accord, il y’a plein de ressource. Quand j’ai un problème je cherche sur google et je trouve 95% du temps.
    Ce dont je parle c’est vraiment de la doc.

  • kontre

    De quel point tu parles, là, exactement ? Je ne te suis pas.

    Y’a sphinx et epydoc qui permettent d’analyser le code source python pour faire de la doc semi-automatique. Je ne pense pas qu’il y ait plus de paramètres dans les fonctions python que pour d’autres langages, au passage. Eventuellement ils peuvent prendre plus de valeurs différentes, mais à part ça…

Leave a comment

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.