Erreurs de conception Python

Il y a quelque temps, alors que j’apprenais le Javascript, j’ai étudié le Javascript: les bons côtés , et j’ai particulièrement apprécié les chapitres sur les parties mauvaises et laides. Bien sûr, je n’étais pas d’accord avec tout, car résumer les défauts de conception d’un langage de programmation est dans une certaine mesure subjectif – même si, par exemple, tout le monde serait d’accord pour dire que le mot-clé était une erreur de Javascript. Néanmoins, je trouve utile de lire de telles critiques: même si on n’est pas d’accord, il y a beaucoup à apprendre.

Existe-t-il une entrée de blog ou un livre décrivant des erreurs de conception pour Python? Par exemple, je suppose que certaines personnes comptent le manque d’optimisation de l’appel de queue comme une erreur; il peut y avoir d’autres problèmes (ou non-problèmes) qui méritent d’être étudiés.

Vous avez demandé un lien ou une autre source, mais il n’y en a pas vraiment. L’information est répartie sur de nombreux endroits différents. Qu’est-ce qui constitue vraiment une erreur de conception et comptez-vous uniquement les problèmes syntaxiques et sémantiques dans la définition du langage ou incluez-vous des éléments pragmatiques tels que les problèmes de plate-forme et de bibliothèque standard et les problèmes d’implémentation spécifiques? On pourrait dire que le dynamisme de Python est une erreur de conception du sharepoint vue des performances, car il rend difficile une implémentation simple et efficace, et rend difficile (je ne dis pas complètement impossible) et d’autres belles choses. Dans le même temps, vous pourriez discuter des avantages des langages dynamics.

Peut-être qu’une approche pour commencer à y penser consiste à examiner les changements de langage de Python 2.x à 3.x. Certaines personnes pourraient bien sûr prétendre que la fonction d’ print est un inconvénient, alors que d’autres pensent que c’est une amélioration. Dans l’ensemble, il n’y a pas beaucoup de changements, et la plupart d’entre eux sont assez petits et subtils. Par exemple, map() et filter() renvoient des iterators au lieu de listes, range() se comporte comme xrange() et les méthodes dict comme dict.keys() renvoient des vues au lieu de listes. Ensuite, il y a quelques changements liés aux entiers, et l’un des grands changements est la gestion des données binarys / chaînes. C’est maintenant du texte et des données , et le texte est toujours Unicode. Il y a plusieurs changements syntaxiques, mais ils concernent davantage la cohérence que la refonte de la langue entière.

De ce sharepoint vue, il semble que Python ait été assez bien conçu au niveau du langage (syntaxe et sémantique) depuis au moins 2.x. Vous pouvez toujours discuter de la syntaxe des blocs basée sur l’indentation, mais nous soaps tous que cela ne mène à rien … 😉

Une autre approche consiste à examiner quelles solutions Python alternatives tentent de résoudre. La plupart d’entre eux abordent les performances d’une manière ou d’une autre, certains abordent des problèmes de plate-forme et d’autres ajoutent ou apportent des modifications au langage lui-même pour résoudre plus efficacement certains types de tâches. Swallow à vide veut rendre Python beaucoup plus rapide en optimisant les étapes de compilation et d’exécution des octets à l’exécution. Stackless ajoute des fonctionnalités pour des applications efficaces et fortement threadées en ajoutant des constructions telles que microtreads et tasklets, des canaux permettant la communication bidirectionnelle des tâches, la planification de l’exécution coopérative ou préventive des tâches et la sérialisation pour suspendre et reprendre l’exécution des tâches. Jython permet d’utiliser Python sur la plate-forme Java et IronPython sur la plate-forme .Net. Cython est un dialecte Python qui permet d’appeler des fonctions C et de déclarer des types C, permettant au compilateur de générer du code C efficace à partir du code Cython. Shed Skin apporte une saisie statique implicite à Python et génère C ++ pour les programmes autonomes ou les modules d’extension. PyPy implémente Python dans un sous-ensemble de Python et modifie certains détails d’implémentation, comme l’ajout de la récupération de place au lieu du comptage de référence. L’objective est de permettre au langage Python et au développement de l’implémentation d’être plus efficaces grâce au langage de plus haut niveau. Py V8 relie Python et JavaScript via le moteur JavaScript V8 – vous pourriez dire que cela résout un problème de plateforme. Psyco est un type spécial de JIT qui génère dynamicment des versions spéciales du code en cours d’exécution pour les données en cours de traitement, ce qui peut accélérer votre code Python sans avoir à écrire de modules C optimisés.

Parmi ceux-ci, on peut dire quelque chose à propos de l’état actuel de Python en examinant PEP-3146, qui décrit la manière dont la déglutition vide sera fusionnée dans CPython. Ce PEP est accepté et constitue donc le jugement des développeurs Python quant à la direction la plus réaliste à prendre pour le moment. Notez que cela concerne les performances, pas la langue en soi.

Donc, je dirais vraiment que les principaux problèmes de conception de Python se situent dans le domaine des performances, mais ce sont essentiellement les mêmes défis que tout langage dynamic et la famille de langages Python tente de résoudre ces problèmes. En ce qui concerne les erreurs de conception telles que celles énumérées dans le Javascript: les bonnes parties , je pense que le sens de “l’erreur” doit être défini de manière plus explicite, mais vous pouvez consulter les remarques et opinions suivantes:

  • FLOSS Weekly 11: Guido van Rossum (podcast du 4 août 2006)
  • Le blog de l’histoire de Python

Existe-t-il une entrée de blog ou un livre décrivant des erreurs de conception pour Python?

Oui.

C’est ce qu’on appelle la liste Py3K des modifications incompatibles avec les versions précédentes.

Commencez ici: http://docs.python.org/release/3.0.1/whatsnew/3.0.html

Lisez toutes les notes de version de Python 3.x pour plus de détails sur les erreurs de Python 2.

Mon plus grand problème avec Python – et ce qui n’a pas été vraiment abordé lors du passage à la version 3.x – est l’absence de conventions de nommage correctes dans la bibliothèque standard.

Pourquoi, par exemple, le module datetime contient-il une classe appelée datetime ? (Pour ne rien dire, pourquoi nous avons des modules datetime et time séparés, mais aussi une classe datetime.time !) Pourquoi datetime.datetime est-il en minuscule, mais decimal.Decimal est en majuscule? Et s’il vous plaît, dites-moi pourquoi nous avons ce terrible bordel dans l’espace de noms xml : xml.sax , mais xml.etree.ElementTree – qu’est-ce qui se passe là-bas?

Ce qui surprend souvent les développeurs inexpérimentés, ce sont les erreurs des candidats. Voici un, arguments par défaut:

http://www.deadlybloodyserious.com/2008/05/default-argument-blunders/

Une de mes langues personnelles est la liaison de noms pour les fonctions lambdas / locales:

 fns = [] for i in range(10): fns.append(lambda: i) for fn in fns: print(fn()) # !!! always 9 - not what I'd naively expect 

IMO, je préférerais de loin rechercher les noms référencés dans un lambda au moment de la déclaration. Je comprends les raisons pour lesquelles cela fonctionne comme ça, mais quand même …

Vous devez actuellement contourner ce problème en liant i dans un nouveau nom dont la valeur ne change pas, en utilisant une fonction de fermeture.

Ceci est plus un problème mineur avec le langage, plutôt qu’une erreur fondamentale, mais: la substitution de propriété. Si vous remplacez une propriété (à l’aide des getters et des setters), il n’y a pas de moyen facile d’obtenir la propriété de la classe parente.

Oui, c’est étrange mais je suppose que c’est ce que vous obtenez pour avoir des variables mutables.

Je pense que la raison est que le “i” se réfère à une boîte qui a une valeur mutable et que la boucle “for” changera cette valeur au fil du temps, donc la lecture de la valeur de la boîte vous donnera la seule valeur disponible. Je ne sais pas comment on pourrait résoudre ce problème en en faisant un langage de programmation fonctionnel sans variables mutables (du moins sans variables mutables non vérifiées).

La solution de contournement que j’utilise consiste à créer une nouvelle variable avec une valeur par défaut (les valeurs par défaut étant évaluées au moment de la définition dans Python, ce qui est gênant à d’autres moments), ce qui entraîne la copie de la valeur dans la nouvelle boîte:

 fns = [] for i in range(10): fns.append(lambda j=i: j) for fn in fns: print(fn()) # works 

Je trouve surprenant que personne n’ait mentionné le verrou d’interpréteur global .

L’une des choses les plus ennuyeuses en Python est d’utiliser writelines () et readlines () sur un fichier. readlines () ne retourne pas seulement une liste de lignes, mais il a aussi toujours les caractères à la fin de chaque ligne, donc vous devez toujours faire quelque chose comme ça pour les supprimer:

 lines = [l.replace("\n", "").replace("\r", "") for l in f.readlines()] 

Et lorsque vous voulez utiliser writelines () pour écrire des lignes dans un fichier, vous devez append \ n à la fin de chaque ligne de la liste avant de les écrire, un peu comme ceci:

 f.writelines([l + "\n" for l in lines]) 

writelines () et readlines () devraient prendre en charge les caractères de fin de ligne indépendamment du système d’exploitation, vous n’avez donc pas à vous en occuper vous-même.

Vous devriez juste pouvoir y aller:

 lines = f.readlines() 

et il devrait retourner une liste de lignes, sans \ n ou \ r caractères à la fin des lignes.

De même, vous devriez juste pouvoir aller:

 f.writelines(lines) 

Pour écrire une liste de lignes dans un fichier, et que celui-ci doit utiliser les caractères de commande préférés des systèmes d’exploitation lors de l’écriture du fichier, vous ne devriez pas avoir à le faire vous-même en premier.

Vous avez demandé des liks; J’ai écrit un document sur ce sujet il y a quelque temps: http://segfaulthunter.github.com/articles/biggestsurprise/

Ma plus grande aversion est range() , car elle ne fait pas ce que vous attendez, par exemple:

 >>> for i in range(1,10): print i, 1 2 3 4 5 6 7 8 9 

Un utilisateur naïf venant d’une autre langue s’attend à recevoir 10 exemplaires.

Je pense qu’il y a beaucoup de choses bizarres dans python dans la manière dont elles gèrent les intégrés / constantes. Comme suit:

 True = "hello" False = "hello" print True == False 

Cela imprime True

 def sorted(x): print "Haha, pwned" sorted([4, 3, 2, 1]) 

Lolwut? Trié est une fonction globale intégrée. Le pire exemple dans la pratique est la list , que les gens ont tendance à utiliser comme nom pratique pour une variable locale et finissent par bafouiller le paramètre intégré global.