Python semble faire fureur ces jours-ci, et non sans honte - car c’est vraiment un langage avec lequel on aime presque se faire donner un nouveau problème à résoudre. Mais, comme un homme sage a dit une fois (l'appeler un homme sage seulement parce que je n'ai aucune idée de qui a dit réellement, pas sûr qu'il était que sage du tout), de savoir vraiment une langue que ne sait pas seulement son syntaxe, design, etc., avantages mais aussi inconvénients. Aucune langue n'est parfaite, certaines sont simplement meilleures que d'autres.
Alors, quels seraient, à votre avis, les inconvénients objectifs de Python.
Remarque: je ne demande pas de comparaison de langage ici (ie C # est meilleur que Python parce que ... yadda yadda yadda) - plus d'un avis objectif (à un certain niveau) sur les fonctionnalités de langage mal conçues vous en manquez, et ainsi de suite. Si doit utiliser une autre langue à titre de comparaison, mais uniquement pour illustrer un point sur lequel il serait difficile de développer autrement (par exemple, pour faciliter la compréhension)
Réponses:
J'utilise assez régulièrement Python, et dans l'ensemble, je considère que c'est un très bon langage. Néanmoins, aucune langue n'est parfaite. Voici les inconvénients par ordre d'importance pour moi personnellement:
C'est lent. Je veux dire vraiment très lent. Bien souvent, cela n'a pas d'importance, mais cela signifie certainement que vous aurez besoin d'un autre langage pour les éléments critiques en termes de performances.
Les fonctions imbriquées sont un peu loufoques car vous ne pouvez pas modifier les variables dans la portée externe. Edit: J'utilise toujours Python 2 en raison de la prise en charge de la bibliothèque, et ce défaut de conception m'irrite énormément, mais apparemment, il a été corrigé dans Python 3 en raison de la déclaration non locale . Je ne peux pas attendre que les bibliothèques que j'utilise soient portées pour que cette faille puisse être envoyée au tas de cendres de l'histoire pour de bon.
Il manque quelques fonctionnalités qui peuvent être utiles au code générique / bibliothèque et IMHO est une simplicité prise à des extrêmes malsains. Les plus importants auxquels je puisse penser sont les types de valeurs définis par l'utilisateur (je suppose que ceux-ci peuvent être créés avec la magie de la métaclasse, mais je n'ai jamais essayé) et le paramètre de la fonction ref.
C'est loin du métal. Besoin d'écrire des primitives de threading ou du code du noyau ou quelque chose? Bonne chance.
Bien que mon incapacité à détecter les erreurs sémantiques dès le départ ne soit pas un inconvénient pour le dynamisme offert par Python, je souhaiterais qu'il existe un moyen de détecter les erreurs syntaxiques et les bêtises, telles que le typage incorrect des noms de variables sans avoir à exécuter le code.
La documentation n’est pas aussi performante que des langages tels que PHP et Java, qui ont de solides ressources en entreprise.
la source
with
déclaration ou les méthodes sur unlist
. Tout ce qui est couvert dans le tutoriel est fondamentalement incompréhensible. J'ai beaucoup plus de chance avec la documentation de Microsoft pour le C ++.Je déteste le fait que Python ne puisse pas faire la distinction entre déclaration et utilisation d'une variable. Vous n'avez pas besoin de dactylographie statique pour y arriver. Ce serait bien d’avoir un moyen de dire «c’est une variable que j’ai délibérément déclarée, et j’ai l’ intention d’introduire un nouveau nom, ce n’est pas une faute de frappe».
De plus, j’utilise généralement les variables Python dans un style non inscriptible, c’est-à-dire que je considère les variables comme étant immuables et ne les modifie pas après leur première affectation. Grâce à des fonctionnalités telles que la compréhension de liste, cela est incroyablement facile et rend le flux de code plus facile à suivre.
Cependant, je ne peux pas documenter ce fait. Rien en Python ne m'empêche d'écraser ou de réutiliser des variables.
En résumé, je voudrais avoir deux mots-clés dans la langue:
var
etlet
. Si j'écris dans une variable non déclarée par l'un ou l'autre, Python devrait générer une erreur. De plus,let
déclare les variables en lecture seule, alors que lesvar
variables sont «normales».Considérons cet exemple:
Notez que les types sont toujours implicites (mais les
let
variables sont typiquement statiques dans la mesure où elles ne peuvent pas être associées à une nouvelle valeur, alors que lesvar
variables peuvent toujours être typées de manière dynamique).Enfin, tous les arguments de méthode doivent être automatiquement
let
, c'est-à-dire qu'ils doivent être en lecture seule. En général, il n'y a aucune bonne raison de modifier un paramètre, à l'exception de l'idiome suivant:Cela pourrait être remplacé par un idiome légèrement différent:
la source
use strict;
etuse warnings;
en Perl sur un script de toute taille. Python a privé le développeur de trop nombreuses aides au débogage.var
etlet
(ou un mécanisme similaire) est un inconvénient. Autrement dit: si j'avais été le concepteur de Python, j'aurais fait quelque chose comme ça. Cela dit , les versions futures pourraient inclure ceci lorsque vous chargez un package spécial (similaire à__future__
). Disimport strict
. Cela n'arrivera pas cependant, car cela nécessite des bidouilles syntaxiques…Mon principal reproche est le threading, qui n'est pas aussi performant dans de nombreuses circonstances (comparé à Java, C et autres) en raison du verrouillage global de l'interpréteur (voir la discussion "À l'intérieur du PILON GIL" (lien PDF) ).
Cependant, il existe une interface multiprocessus très facile à utiliser, mais elle sera plus lourde en mémoire pour le même nombre de processus que de threads, ou difficile si vous avez beaucoup de données partagées. L’avantage, cependant, est qu’une fois que vous avez un programme fonctionnant avec plusieurs processus, il peut s’adapter à plusieurs machines, ce qu’un programme threadé ne peut pas faire.
Je suis vraiment en désaccord sur la critique de la documentation, je pense que celle-ci est excellente et meilleure que la plupart, sinon toutes les langues principales.
Aussi, vous pouvez attraper de nombreux bugs d'exécution exécutant pylint .
la source
On peut soutenir que le manque de typage statique, qui peut introduire certaines classes d’ erreurs d’ exécution , ne vaut pas la flexibilité supplémentaire offerte par le typage de canard.
la source
int foo = 4; Console.Write(foo.Length);
compilation n’est pas compilée; l’erreur "Int32 n’a pas de propriété Length" ne peut donc pas se retrouver accidentellement dans les logiciels publiés. En python, à moins que vous n'exécutiez des outils secondaires facultatifs pour rechercher de telles erreurs, le code qui accède à des membres d'objets non existants peut être non détecté jusqu'à ce qu'il provoque des erreurs d'exécution.Je pense que les parties orientées objet de Python sont un peu "verrouillées". Tout le besoin de passer explicitement "soi" à chaque méthode est un symptôme indiquant que sa composante POO n'a pas été expressément planifiée , pourrait-on dire; il montre également les règles de portée parfois verruqueuses de Python qui ont été critiquées dans une autre réponse.
Modifier:
Quand je dis que les parties orientées objet de Python se sentent «bloquées», je veux dire que, parfois, le côté POO se sent plutôt incohérent. Prenez Ruby, par exemple: En Ruby, tout est un objet et vous appelez une méthode en utilisant la
obj.method
syntaxe habituelle (à l'exception des opérateurs surchargés, bien sûr); en Python, tout est aussi un objet, mais certaines méthodes sont appelées comme une fonction; c'est-à-dire que vous surchargez__len__
pour renvoyer une longueur, mais appelez-le en utilisantlen(obj)
le commun plus familier (et cohérent)obj.length
dans d'autres langues. Je sais que cette décision de conception a des raisons, mais je ne les aime pas.De plus, le modèle de programmation orientée objet de Python ne dispose d'aucune sorte de protection des données, c'est-à-dire qu'il n'y a pas de membres privés, protégés et publics; vous pouvez les imiter en utilisant
_
et__
en face de méthodes, mais c'est un peu moche. De la même manière, Python ne comprend pas non plus correctement l'aspect de la programmation orientée objet qui consiste à transmettre les messages.la source
Ce que je n'aime pas chez Python:
lambda
ne peut contenir qu'une seule expression).cin
ouscanf
en C ++ et C ouScanner
en Java).la source
raw_input
et 'sys.stdin' sont de jolis barebones. Ils ne prennent pas en charge l’obtention d’une entrée formatée (par exemple, quelque chose comme "% d:% d:% d"% (heure, minute, seconde) à lire en temps voulu). Jusqu'à présent, Python n'a rien qui s'approche des fonctionnalités de scanf (en C) ou de Scanner (Java).Arguments par défaut avec des types de données mutables.
C'est généralement le résultat de quelques bugs subtils. Je pense qu'il serait préférable de créer un nouvel objet de liste chaque fois qu'un argument par défaut était requis (plutôt que de créer un seul objet à utiliser pour chaque appel de fonction).
Edit: Ce n'est pas un gros problème, mais quand quelque chose doit être mentionné dans la documentation, cela signifie généralement que c'est un problème. Cela ne devrait pas être nécessaire.
Surtout quand cela aurait dû être la valeur par défaut. C'est juste un comportement étrange qui ne correspond pas à ce que vous attendez et qui n'est pas utile dans un grand nombre de circonstances.
la source
Certaines des fonctionnalités de Python qui le rendent aussi flexible en tant que langage de développement sont également considérées comme des inconvénients majeurs par ceux utilisés pour l'analyse statique du "programme entier" réalisée par le processus de compilation et de liaison dans des langages tels que C ++ et Java.
Les variables locales sont déclarées à l'aide de l'instruction d'affectation ordinaire. Cela signifie que les compilations de variables dans toute autre étendue nécessitent la saisie d'annotations explicites par le compilateur (déclarations globales et non locales pour les étendues externes, notation d'accès d'attributs pour les étendues d'exemple). Cela réduit considérablement la quantité de passe-partout nécessaire lors de la programmation, mais signifie que des outils d'analyse statique tiers (tels que pyflakes) sont nécessaires pour effectuer les contrôles gérés par le compilateur dans des langages nécessitant des déclarations de variables explicites.
Le contenu des modules, des objets de classe et même de l'espace de noms intégré peut être modifié au moment de l'exécution. C'est extrêmement puissant, permettant de nombreuses techniques extrêmement utiles. Cependant, cette flexibilité signifie que Python n'offre pas certaines fonctionnalités communes aux langages OO à typage statique. Plus particulièrement, le paramètre "self" des méthodes d'instance est explicite plutôt qu'implicite (puisque les "méthodes" ne doivent pas être définies dans une classe, elles peuvent être ajoutées ultérieurement en modifiant la classe, ce qui signifie qu'elle n'est pas particulièrement pratique. de passer implicitement la référence d'instance) et les contrôles d'accès d'attribut ne peuvent pas être facilement appliqués, que le code soit ou non "à l'intérieur" ou "à l'extérieur" de la classe (car cette distinction n'existe que pendant l'exécution de la définition de la classe).
Ceci est également vrai de nombreux autres langages de haut niveau, mais Python a tendance à faire abstraction de la plupart des détails matériels. Les langages de programmation système tels que C et C ++ conviennent toujours beaucoup mieux à la gestion des accès matériels directs (cependant, Python communiquera volontiers avec ceux-ci via des modules d'extension CPython ou, de manière plus portable, via la
ctypes
bibliothèque).la source
Exemple pour le cadrage brisé; transcription de la session d'interprétation:
global
et desnonlocal
mots-clés ont été introduits pour patcher cette stupidité de conception.la source
global
ou desnonlocal
mots - clés en Python. Tellement rarement que j'oublie que ce problème existe et que je dois le re-rechercher à plusieurs reprises, malgré le fait que j'écris du code Python tous les jours au travail. Pour moi, le code qui doit modifier les variables globales (ou pire, les variables externes non globales) est une odeur de code. Il y a généralement (pas toujours) un meilleur moyen.Je trouve la combinaison de syntaxe orientée objet
this.method()
et procédurale / fonctionnelle de Pythonmethod(this)
très dérangeante:Cela est particulièrement grave car un grand nombre de fonctions (plutôt que de méthodes) sont simplement vidées dans l’ espace de noms global : méthodes relatives aux listes, chaînes, nombres, constructeurs, métaprogrammation, toutes mélangées dans une grande liste triée par ordre alphabétique.
À tout le moins, les langages fonctionnels comme F # ont toutes les fonctions correctement espacées dans les modules:
Donc, ils ne sont pas tous ensemble. De plus, il s'agit d'une norme suivie dans toute la bibliothèque, donc au moins elle est cohérente.
Je comprends les raisons de faire la fonction fonction vs méthode , mais je pense toujours que c'est une mauvaise idée de les mélanger comme ça. Je serais beaucoup plus heureux si la méthode-syntaxe était suivie, du moins pour les opérations courantes:
Que les méthodes mutent ou non, les avoir comme méthodes sur l'objet présente plusieurs avantages:
Module
lorsque vous appelezModule.method(x)
. En prenant l'exemple de la liste fonctionnelle ci-dessus, pourquoi dois-je continuer à répéterList
encore et encore? Il faut savoir que c'est unList
et je ne veux pas appeler laNavigation.map()
fonction dessus! En utilisant lax.map()
syntaxe, cela reste sec et toujours non ambigu.Et bien sûr, cela présente des avantages par rapport à la manière de tout mettre en place dans un espace de noms global . Ce n'est pas que la manière actuelle est incapable de faire avancer les choses. C'est même assez concis (
len(lst)
), puisque rien n'est espacé! Je comprends les avantages d'utiliser des fonctions (comportement par défaut, etc.) par rapport aux méthodes, mais je ne l'aime toujours pas.C'est juste en désordre. Et dans les grands projets, le désordre est votre pire ennemi.
la source
len()
est une fonction, et quels sont les avantages. J'ai également expliqué pourquoi je pense que c'est une mauvaise idée, pourquoi je pense que les fonctions globales sont une idée particulièrement mauvaise, et pourquoi je pense que les méthodes constituent un moyen pratique d'organiser et de définir la fonctionnalité de votre fonctionnalité =)def
,class
et d’autres appels non fonctionnels. Comparez cela avec 100+ dans la plupart des autres langues populaires. Aussi, pensez à la ligne deimport this
:Namespaces are one honking great idea -- let's do more of those!
. Je pense que vous pourriez mal comprendre les espaces de noms Python;)Manque d' homoiconicité .
Python a dû attendre 3.x pour ajouter un mot clé "avec". Dans n'importe quel langage homoiconique, il aurait pu être trivialement ajouté dans une bibliothèque.
La plupart des problèmes que j'ai vus dans les réponses sont de l'un des 3 types suivants:
1) Choses qui peuvent être corrigées avec un outillage (par exemple pyflakes) 2) Détails de mise en œuvre (GIL, performance) 3) Choses qui peuvent être corrigées avec des normes de codage (c.-à-d. Caractéristiques que les gens souhaiteraient ne pas avoir là)
La langue n ° 2 n’est pas un problème de langue, les questions n ° 1 et n ° 3 de l’OMI ne sont pas graves.
la source
with
était disponible depuis Python 2.5 avecfrom __future__ import with_statement
, mais je suis d’accord, j’ai parfois trouvé regrettable que des déclarations commeif
/for
/print
/ etc soient "spéciales" au lieu de fonctions normalesLe python est mon langage préféré car il est très expressif, mais vous empêche toujours de faire trop d’erreurs. J'ai encore quelques petites choses qui m'ennuient:
Pas de vraies fonctions anonymes. Lambda peut être utilisé pour des fonctions à instruction unique, et l'
with
instruction peut être utilisée pour beaucoup de choses pour lesquelles vous utiliseriez un bloc de code en Ruby. Mais dans certaines situations, cela rend les choses un peu plus maladroites qu’elles ne le devraient. (Loin d'être aussi maladroit que cela serait en Java, mais quand même ...)Une certaine confusion dans la relation entre les modules et les fichiers. Exécuter "python foo.py" à partir de la ligne de commande est différent de "import foo". Les importations relatives dans Python 2.x peuvent également causer des problèmes. Néanmoins, les modules de Python sont tellement meilleurs que les fonctionnalités correspondantes de C, C ++ et Ruby.
Explicite
self
. Même si j'en comprends certaines des raisons et même si j'utilise Python quotidiennement, j'ai tendance à faire l'erreur de l'oublier. Un autre problème est qu’il devient un peu fastidieux de faire une classe d’un module. Le soi explicite est lié à la portée limitée dont d'autres se sont plaints. La plus petite portée en Python est la portée de la fonction. Si vous limitez vos fonctions, comme vous le devriez, ce n'est pas un problème en soi et IMO fournit souvent un code plus propre.Certaines fonctions globales, telles que
len
celle que vous vous attendriez à être une méthode (qui est en réalité en coulisse).Indentation significative. Ce n’est pas l’idée elle-même, ce qui me semble formidable, mais comme c’est la seule chose qui empêche tant de gens d’essayer Python, il serait peut-être préférable que Python utilise des symboles de début / fin (facultatifs). En ignorant ces personnes, je pourrais totalement vivre avec une taille imposée pour l'indentation aussi.
Qu'il ne s'agit pas du langage intégré des navigateurs Web, au lieu de JavaScript.
Parmi ces plaintes, ce n’est que la première qui me tient suffisamment à cœur et qui, à mon avis, devrait être ajoutée à la langue. Les autres sont plutôt mineurs, sauf le dernier, ce qui serait bien si cela se produisait!
la source
datetime.datetime.now()
quand un projet pouvait écriredatetime.now
et ensuite mélanger deux projets, une façon de l'écrire exclut l'autre et sûrement cela ne se serait pas produit en Java qui ne nommerait pas un module de la même manière qu'un fichier. (?) Si vous voyez comment le module nous confond avec le fichier lorsque les deux utilisations sont pratiquées et explicites,self
j'essaie encore de comprendre car les appels n'ont pas le même nombre d'arguments que les fonctions. Et vous pourriez penser que la VM python est lente?Python n’est pas complètement mature: le langage Python 3.2 présente actuellement des problèmes de compatibilité avec la plupart des paquets actuellement distribués (ils sont généralement compatibles avec Python 2.5). C’est un gros inconvénient qui nécessite actuellement plus d’efforts de développement (trouver le paquet requis; vérifier la compatibilité; peser, choisir un paquet moins performant qui pourrait être plus compatible; prendre la meilleure version, la mettre à jour en 3.2, ce qui pourrait prendre plusieurs jours, puis commence à faire quelque chose d'utile).
Probablement à la mi-2012, ce sera moins un inconvénient.
Notez que je suppose que je me suis fait avoir par un fan-boy. Lors d'une discussion entre développeurs, notre équipe de développeurs de haut niveau est parvenue à la même conclusion.
La maturité dans un sens principal signifie qu'une équipe peut utiliser la technologie et être très rapidement opérationnelle sans risques cachés (y compris les problèmes de compatibilité). Les packages Python tiers et de nombreuses applications ne fonctionnent pas sous 3.2 pour la majorité des packages actuels. Cela crée plus de travail d'intégration, de test, de réimplémentation de la technologie elle-même au lieu de résoudre le problème actuel == une technologie moins mature.
Mise à jour pour juin 2013: Python 3 a toujours des problèmes de maturité. De temps en temps, un membre de l’équipe mentionnera un paquet nécessaire puis dira "sauf que ce n’est que pour la version 2.6" (dans certains cas, j’ai implémenté une solution de contournement via le socket localhost pour utiliser le package réservé à la version 2.6 avec 2.6, et le reste de nos outils restent avec 3.2). Même MoinMoin, le wiki pur-python, n’est pas écrit en Python 3.
la source
La portée de Python est sérieusement brisée, ce qui rend la programmation orientée objet en Python très délicate.
la source
self.
devant chaque référence à une propriété d'instance et à une méthode. Cela rend impossible l'utilisation de Python pour créer un DSL comme c'est si facile à faire en Ruby.Mes reproches à propos de Python:
la source
Les modificateurs d'accès en Python ne sont pas applicables. Il est donc difficile d'écrire du code bien structuré et modularisé.
Je suppose que cela fait partie de la portée brisée de @ Mason - un gros problème en général avec cette langue. Pour un code censé être lisible, il semble assez difficile de déterminer ce qui peut et devrait être dans la portée et quelle valeur sera à un moment donné - je pense actuellement à passer du langage Python à cause de ces inconvénients .
Ce n'est pas parce que "nous sommes tous des adultes consentants" que nous ne commettons pas d'erreurs et que nous ne travaillons pas mieux avec une structure solide, en particulier lorsque vous travaillez sur des projets complexes - l'indentation et les soulignés sans signification ne semblent pas suffisants .
la source
Mais il a quelques fonctionnalités intéressantes:
la source
Je préfère Python et le premier inconvénient qui me vient à l’esprit est de commenter une déclaration comme celle-ci:
if myTest():
vous devez modifier l’indentation de tout le bloc exécuté, ce qui n’aurait rien à voir avec C ou Java. En fait, en python au lieu de commenter une clause if, j'ai commencé à le commenter de la manière suivante: `si True: #myTest (), je n'aurai donc pas à changer le bloc de code suivant. Puisque Java et C ne s'appuient pas sur l'indentation, il est plus facile de commenter des déclarations avec C et Java.la source
if something()
pourif False and something()
. Une autre astuce consiste à "commenter" à l'aide d'une chaîne de plusieurs lignes.L'envoi multiple ne s'intègre pas bien avec le système de type à envoi unique établi et n'est pas très performant.
Le chargement dynamique est un problème majeur sur les systèmes de fichiers parallèles où la sémantique de type POSIX provoque des ralentissements catastrophiques pour les opérations nécessitant beaucoup de métadonnées. J'ai des collègues qui ont brûlé un quart de million d'heures de base en obtenant simplement le chargement de Python (avec numpy, mpi4py, petsc4py et autres modules d'extension) sur des cœurs de 65k. (La simulation a fourni de nouveaux résultats scientifiques significatifs, donc cela en valait la peine, mais c'est un problème lorsque plus d'un baril de pétrole est brûlé pour charger Python une fois.) temps de chargement raisonnables à l’échelle, y compris le correctif de libc-rtld pour permettre
dlopen
un accès collectif au système de fichiers.la source
dlopen
est dans notre bibliothèque collfs . Ce référentiel contient également des astuces ZipImport supplémentaires inspirées par la mise en cache de chemin d'Asher Langton. Nous travaillons sur une meilleure distribution et un papier.Quoi qu'il en soit, le python est ma langue principale depuis 4 ans maintenant. Etre fanboys, élitistes ou monomanes ne fait pas partie de la culture des pythons.
la source
len(s)
à travers__len__(self)
et autres "méthodes spéciales"__add__
et__iadd__
pour+
et+=
)self
comme premier paramètre de méthodela source
"Immutabilité" n'est pas exactement son point fort. Autant que je sache, les nombres, les n-uplets et les chaînes sont immuables, tout le reste (objets) est modifiable. Comparez cela à des langages fonctionnels comme Erlang ou Haskell où tout est immuable (du moins par défaut).
Cependant, Immutability brille vraiment avec la concurrence *, ce qui n'est pas non plus le point fort de Python, donc au moins c'est conséquent.
(* = Pour les nitpickers: je veux dire une concurrence simultanée, au moins partiellement parallèle. Je suppose que Python accepte les communications simultanées "à un seul thread", dans lesquelles l'immuabilité n'est pas aussi importante. super même sans concurrence.))
la source
J'aimerais avoir explicitement des constructions parallèles. Le plus souvent, quand j'écris une liste de compréhension comme
Je me fiche de l'ordre dans lequel les éléments seront traités. Parfois, je ne me soucie même pas de l'ordre dans lequel ils sont renvoyés.
Même si CPython ne peut pas le faire correctement lorsque mon f est pur Python, un comportement comme celui-ci pourrait être défini pour être utilisé par d'autres implémentations.
la source
Python n’a pas d’optimisation de l’appel final, principalement pour des raisons philosophiques . Cela signifie que la récurrence de la queue sur des structures volumineuses peut coûter de la mémoire O (n) (en raison de la pile inutile qui est conservée) et vous obliger à réécrire la récursivité sous forme de boucle pour obtenir la mémoire O (1).
la source