Quels sont les inconvénients de Python? [fermé]

147

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)

Tour
la source
50
Je pense que c'est une question subjective utile, et il serait dommage de la fermer.
Eric Wilson
25
Il semble y avoir un fan de python ici qui ne fait que voter contre toutes les réponses anti-python.
Zvrba
2
@TMN: Cela traite toujours les espaces blancs comme des jetons, mais ne les renvoie pas - et c'est exactement ce que la grammaire de Python fait aussi.
9
@Roger: la convention sur SO est de commenter les votes négatifs. Comme il s’agit d’un site pour des opinions subjectives , je ne vois aucune raison pour les votes négatifs, en particulier. sans commentaires. Donc, je me tiens à mon "nom d'appel".
Zvrba
8
@zvrba: Les votes négatifs signifient toujours "inutile", comme toujours.

Réponses:

109

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:

  1. 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.

  2. 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.

  3. 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.

  4. C'est loin du métal. Besoin d'écrire des primitives de threading ou du code du noyau ou quelque chose? Bonne chance.

  5. 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.

  6. La documentation n’est pas aussi performante que des langages tels que PHP et Java, qui ont de solides ressources en entreprise.

dsimcha
la source
60
@ Casey, je ne suis pas d'accord. L’index est horrible - essayez de rechercher la withdéclaration ou les méthodes sur un list. 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 ++.
Mark Ransom
17
Environ 5 - utilisez simplement pyflakes. Il est écrit pour attraper exactement ces erreurs.
Alexander Solovyov
4
Concernant la vitesse: avec l’avènement de PyPy, de nombreux utilisateurs de Python seront désormais en mesure de gérer le problème de vitesse simplement en utilisant un interpréteur avec un compilateur JIT intégré (pour l’instant, les utilisateurs de Python 3 et ceux de modules d’extension C non gérés par cpyext). ne pas avoir cette option).
ncoghlan
29
Je méprise les documents Python. Ils sont certes plus jolis que la plupart des gens, mais souvent, de nombreuses informations utiles sont regroupées dans une seule page, telles que les méthodes sur les chaînes et les listes - et tous les types de séquence sont également regroupés. Quand je cherche cette information, je tombe sur un gros volume et je dois chercher en bas de la page pour trouver ce que je veux. Je trouve également difficile de lire l'index de ces pages et il est parfois difficile de dire quelle section je veux.
Carson Myers
5
Comment la distance au métal peut-elle être un argument? Python s'est-il jamais prétendu être un langage système?
Mark Canlas
66

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: varet let. 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, letdéclare les variables en lecture seule, alors que les varvariables sont «normales».

Considérons cet exemple:

x = 42    # Error: Variable `x` undeclared

var x = 1 # OK: Declares `x` and assigns a value.
x = 42    # OK: `x` is declared and mutable.

var x = 2 # Error: Redeclaration of existing variable `x`

let y     # Error: Declaration of read-only variable `y` without value
let y = 5 # OK: Declares `y` as read-only and assigns a value.

y = 23    # Error: Variable `y` is read-only

Notez que les types sont toujours implicites (mais les letvariables sont typiquement statiques dans la mesure où elles ne peuvent pas être associées à une nouvelle valeur, alors que les varvariables 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:

def foo(bar = None):
    if bar == None: bar = [1, 2, 3]

Cela pourrait être remplacé par un idiome légèrement différent:

def foo(bar = None):
    let mybar = bar or [1, 2, 3]
Konrad Rudolph
la source
6
Je souhaite tellement Python avait une déclaration "var". Outre la (très bonne) raison que vous énoncez, cela faciliterait également la lecture du code car vous pourrez alors parcourir la page pour repérer toutes les déclarations de variables.
Jhocking
25
C'est comme si les développeurs python avaient ignoré les leçons du passé. Ne pas déclarer de variables, pas de fonctions, est une erreur commise pour la première fois dans les années cinquante. Ces bogues difficiles à trouver qui résultaient d’une faute de frappe difficile à repérer ont été étonnamment créés pour la première fois dans les années 1950. Cette erreur de langage a été commise (et corrigée ultérieurement) maintes et maintes fois. La déclaration de variables n'est pas un fardeau énorme. Il a sauvé mes fesses plusieurs fois. Je dois inévitablement use strict;et use warnings;en Perl sur un script de toute taille. Python a privé le développeur de trop nombreuses aides au débogage.
David Hammen le
19
@David, Pour être juste avec python, cela déclenchera une exception si vous essayez d'accéder à une variable qui n'a pas été affectée. Beaucoup de langues sans déclaration renverraient une sorte de valeur par défaut. En conséquence, la version de Python est beaucoup moins problématique que celles-là.
Winston Ewert
1
@yi_H La proposition n'était pas censée être rétro-compatible - ni même une vraie proposition. La question était de savoir «quels sont les inconvénients de Python»… eh bien, ne pas avoir varet let(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__). Dis import strict. Cela n'arrivera pas cependant, car cela nécessite des bidouilles syntaxiques…
Konrad Rudolph le
3
+1 Pour ajouter de meilleures capacités de programmation "fonctionnelles".
Evan Plaice
44

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 .

Casey
la source
2
+1 pour pylint. Je n'étais pas au courant. La prochaine fois que je fais un projet en Python, je vais l'essayer. En outre, le multithreading semble fonctionner correctement si vous utilisez Jython au lieu de l'implémentation CPython de référence. OTOH Jython est un peu plus lent que CPython, cela peut donc partiellement défaire le but recherché.
Dsimcha
3
Le filetage n'est pas bien pris en charge? Les bibliothèques de threading y sont depuis avant 2.1.
Rox0r
2
Je sais qu'il existe un support de threading, mais comparé à Java ou C, le GIL réduira réellement vos performances. C'est pourquoi le module de multitraitement est préféré au threading.
cmcginty
2
La documentation est bonne si vous parvenez à la trouver. Googler les classes Java est beaucoup plus facile que Python.
Brendan Long
@ Casey J'ai clarifié le libellé de la réponse, car le filetage est pris en charge, il affiche juste quelques performances étranges (ajouté une référence et quelques liens vers docs aussi)
dbr
28

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.

Jacob
la source
5
C'est correct, bien qu'il existe des outils tels que PyChecker qui peuvent vérifier les erreurs qu'un compilateur dans des langages comme C / Java ferait.
Oliver Weiler
24
Le typage dynamique est une décision de conception consciente et non un inconvénient.
missingfaktor
14
C'est la même chose que de dire que la faiblesse de Java est le manque de frappe dynamique.
MAK
12
@missingfaktor, @MAK, la frappe de canard était évidemment une fonctionnalité recherchée. Mais la plupart des décisions de conception introduisent des avantages et des inconvénients objectifs. La souplesse de code ajoutée est un avantage du typage dynamique et les classes supplémentaires d'erreurs d'exécution potentielles constituent un inconvénient. La partie subjective est de savoir si la fonctionnalité en vaut la peine.
Jacob
6
L'absence de typage statique permet aux programmeurs d'écrire plus facilement du code comportant des erreurs d'exécution. En C #, la 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.
Jacob
27

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.methodsyntaxe 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 utilisant len(obj)le commun plus familier (et cohérent) obj.lengthdans 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.

mipadi
la source
17
Le paramètre self rend simplement explicite ce que les autres langages laissent implicite. Ces langues ont clairement un paramètre "self".
13
@Roger Pate: Oui, mais ce besoin explicite de "soi" est un peu gênant (et, dirais-je, une abstraction qui fuit). Cela n’a pas non plus été décidé délibérément en matière de conception, mais en raison des règles "étranges" de Python. Je ne trouve pas l'article rapidement, mais un courrier électronique de Guido van Rossum explique bien pourquoi le paramètre "self" est requis.
mardi
2
@Roger Pate: dans les langages orientés objet, le fait de passer la cible en tant que premier paramètre peut toujours être considéré comme un détail d'implémentation. Mon point, cependant, n'est pas de savoir si c'est une bonne idée ou non; le fait est qu'en Python, ce n'est pas dû à une décision de conception consciente, mais plutôt au fait de contourner les verrues dans le système de cadrage.
mardi
3
@mipadi: La mise à jour a un meilleur raisonnement (donc je supprimerai le vote négatif), mais si vous considérez len comme un opérateur que vous surchargez, c'est plus de OO en Python. J'adorerais voir un exemple ou un raisonnement sur la façon dont Python parvient à mal faire passer les messages.
8
Le soi explicite découle du fait que les méthodes ne sont que des fonctions (et, comme Winston l'a noté, des déclarations de variables locales implicites). Vous êtes libre de ne pas aimer cette décision de conception, mais appeler "POO" dans un langage où tout est accessible en tant qu'objet à l'exécution est ridicule.
ncoghlan
19

Ce que je n'aime pas chez Python:

  1. Threading (je sais que cela a déjà été mentionné, mais mérite d'être mentionné dans tous les posts).
  2. Pas de support pour les fonctions anonymes multilignes ( lambdane peut contenir qu'une seule expression).
  3. Absence d'une fonction / classe de lecture d'entrée simple mais puissante (comme cinou scanfen C ++ et C ou Scanneren Java).
  4. Toutes les chaînes ne sont pas unicode par défaut (mais corrigées dans Python 3).
MAK
la source
5
En ce qui concerne (2), je pense que cela est compensé par la possibilité d’avoir des fonctions imbriquées.
Konrad Rudolph
3
@ KonradRudolph Mon problème principal avec des fonctions imbriquées au lieu de plusieurs lambda est que l'ordre de lecture est interverti.
CookieOfFortune
2
@wkschwartz: raw_inputet '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).
MAK
2
@limscoder: Toutes les chaînes sont unicode par défaut en Java. Je ne vois pas de bonne raison d'avoir des classes str et unicode séparées. IMHO, les chaînes et les tableaux d'octets ne doivent pas être représentés par la même abstraction. Une classe de chaînes de caractères devrait être destinée à stocker et à manipuler du texte - dont la représentation interne ne nous intéresse pas vraiment. Nous ne devrions pas vouloir faire des choses comme tronquer / remplacer / supprimer / insérer à un octet spécifique dans une chaîne - nous voulons faire cela à un caractère spécifique . Il est facile d'oublier la distinction et de faire exploser votre code lorsque vous utilisez une entrée non anglaise.
MAK
1
@limscoder: si vous voulez voir un unicode facile, essayez Tcl. Il ya quelques années, j’ai dû passer de Tcl à Python, et j’ai été surpris de constater à quel point le support Unicode de python primitif est en comparaison. C'est vraiment invisible dans Tcl, et une douleur majeure dans le python.
Bryan Oakley
18

Arguments par défaut avec des types de données mutables.

def foo(a, L = []):
    L.append(a)
    print L

>>> foo(1)
[1]
>>> foo(2)
[1, 2]

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.

def foo(a, L = None):
    if L is None:
        L = []
    ...

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.

jsternberg
la source
Je vois beaucoup de plaintes à ce sujet, mais pourquoi les gens insistent-ils pour avoir une liste vide (que la fonction modifie) comme argument par défaut? Est-ce vraiment un gros problème? Ie, est-ce un vrai problème?
Martin Vilcans
8
Cela viole le principe de la moindre surprise. On ne s'attendrait pas à ce que les paramètres d'une fonction survivent d'un appel à l'autre
aib
C'est une conséquence qu'il s'agisse d'un langage de script. Vous ne serez dérouté par ce bug qu'une fois, et plus jamais. Trouver ce bogue par vous-même vous donne vraiment un coup de pied pour vous rappeler que oui, il s'agit toujours d'un langage de script. Et ce n’est que parce que le langage cache très bien l’aspect script (en supposant que vous l’utilisez correctement).
Zoran Pavlovic
@ZoranPavlovic, par curiosité, pourquoi est-ce une conséquence du langage de script? Il semble y avoir un problème avec le moment où les données sont liées et parce que les listes sont mutables (deux choses qui sont normalement bonnes, mais qui finissent par être mauvaises lorsqu'elles sont combinées). Le même problème peut survenir dans un langage sans script si vous avez lié les données au moment de la création de la fonction plutôt que de créer une nouvelle liste à chaque appel de la fonction.
Jsternberg
@aib: Je ne pense pas - le paramètre ici, comme tout autre objet Python - est un pointeur sur un objet. Dans ce cas, l'objet est un objet mutable et la variable est liée lorsque la fonction est déclarée. Le paramètre "survit à travers les appels", mais ce qui reste est la référence à un objet mutable.
Patrick Collins
14

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.

  • Déclaration implicite de variables locales

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.

  • "Monkey patcher" est supporté

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).

  • Loin du métal

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 ctypesbibliothèque).

ncoghlan
la source
12
  1. Utilisation de l'indentation pour les blocs de code au lieu de {} / begin-end, peu importe.
  2. Chaque nouvelle langue moderne a une portée lexicale appropriée, mais pas Python (voir ci-dessous).
  3. Documentation chaotique (à comparer avec la documentation Perl5, qui est superbe).
  4. Strait-jacket (il n'y a qu'une seule façon de le faire).

Exemple pour le cadrage brisé; transcription de la session d'interprétation:

>>> x=0
>>> def f():
...     x+=3
...     print x
... 
>>> f()
Traceback (most recent call last):
  File "", line 1, in ?
  File "", line 2, in f
UnboundLocalError: local variable 'x' referenced before assignment

globalet des nonlocalmots-clés ont été introduits pour patcher cette stupidité de conception.

zvrba
la source
2
En ce qui concerne la portée, il serait utile que les curieux consultent python.org/dev/peps/pep-3104 pour comprendre le raisonnement de la méthode actuelle.
Winston Ewert
D'accord avec +1. Donc, +1.
Jas
34
Avoir un moyen de le faire est un avantage. Lorsque vous lisez le code de quelqu'un d'autre, vous n'avez pas à déchiffrer une seule déclaration. Une fois que les idiomes sont câblés dans votre cerveau, vous devriez avoir une reconnaissance instantanée.
Rox0r
9
Totalement d'accord avec @ rox0r. La «veste droite» empêche toutes sortes de guerres de syntaxe.
keithjgrant
8
Pour être honnête, j'ai très rarement besoin du globalou des nonlocalmots - 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.
Ben
11

Je trouve la combinaison de syntaxe orientée objet this.method()et procédurale / fonctionnelle de Python method(this)très dérangeante:

x = [0, 1, 2, 3, 4]
x.count(1)
len(x)
any(x)
x.reverse()
reversed(x)
x.sort()
sorted(x)

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:

List.map(x)
List.reversed(x)
List.any(x)

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:

x.count(1)
x.len()
x.any()
x.reverse()
x.reversed()
x.sort()
x.sorted()

Que les méthodes mutent ou non, les avoir comme méthodes sur l'objet présente plusieurs avantages:

  • Emplacement unique pour rechercher les opérations "communes" sur un type de données: autres bibliothèques / etc. peuvent avoir d'autres choses fantaisistes à faire avec les types de données mais les opérations "par défaut" sont toutes dans les méthodes de l'objet.
  • Pas besoin de continuer à répéter Modulelorsque vous appelez Module.method(x). En prenant l'exemple de la liste fonctionnelle ci-dessus, pourquoi dois-je continuer à répéter Listencore et encore? Il faut savoir que c'est un Listet je ne veux pas appeler la Navigation.map()fonction dessus! En utilisant la x.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.

Haoyi
la source
1
ouais ... Le style LINQ me manque vraiment (je suis sûr que LINQ n'est pas le premier à l'implémenter, mais je le connais bien) la gestion de la liste.
CookieOfFortune
1
Ne pensez pas à len (x) en tant que méthode. "len" est une fonction. Python a des fonctions et des méthodes et je ne vois rien de mal à cette approche. Le manque de fonctions appropriées est généralement la source de nombreuses saisies inutiles.
rbanffy
Je sais 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é =)
Haoyi
Je ne pense pas que 42 (ou est-ce 43?) Mots-clés est un "grand" nombre. Cela inclut également des choses comme def, classet d’autres appels non fonctionnels. Comparez cela avec 100+ dans la plupart des autres langues populaires. Aussi, pensez à la ligne de import 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;)
Wayne Werner le
8

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.

Aidenn
la source
1
withétait disponible depuis Python 2.5 avec from __future__ import with_statement, mais je suis d’accord, j’ai parfois trouvé regrettable que des déclarations comme if/ for/ print/ etc soient "spéciales" au lieu de fonctions normales
dbr
7

Le 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' withinstruction 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 lencelle 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!

Martin Vilcans
la source
+1 Cela me fait me demander si écrire datetime.datetime.now()quand un projet pouvait écrire datetime.nowet 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, selfj'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?
Niklas Rosencrantz
En ce qui concerne votre problème avec le mot clé explicite self. Puis-je suggérer d'utiliser un bon IDE python pour cela? Je sais que PyDev sur Eclipse complète automatiquement la partie autonome d'une signature de fonction s'il détecte que vous écrivez dans une classe.
Zoran Pavlovic
5

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.

Jonathan Cline IEEE
la source
2
Je ne suis d'accord avec vous que si votre définition de la maturité n'est pas compatible avec une version incompatible par sa conception .
Tshepang
3
Je conviens que les deux flux incompatibles de python posent un problème (bien que l'on comprenne bien pourquoi cela a été fait), mais je ne considère pas cela comme un problème de "maturité".
Winston Ewert le
La maturité, dans un sens, 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.
Jonathan Cline IEEE
2
Ensuite, utilisez simplement Python 2.x. Vous savez ... la version que tout le monde utilise. Ou lisez la documentation du paquetage pendant 2 secondes pour déterminer les versions avec lesquelles il est compatible.
Jsternberg
2
"Ce n'est pas parce que Python 3.0 est publié depuis un certain temps que c'est la version que vous devez utiliser. Python 3.0 et 2.x sont développés en même temps. J'espère qu'à l'avenir nous pourrons tous utiliser Python 3.0, mais pour l’instant, utiliser 2.x est une bonne solution "-> C’est une façon de dire 500 caractères: Ce n’est pas encore mature.
Jonathan Cline IEEE
4

La portée de Python est sérieusement brisée, ce qui rend la programmation orientée objet en Python très délicate.

Maçon Wheeler
la source
8
Pouvez-vous donner un exemple? (Je suis sûr que vous avez raison, mais j'aimerais un exemple.)
Winston Ewert Le
24
J'aime Python mais je méprise absolument de devoir mettre 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.
Adam Crossland
35
Je ne trouve pas le moi maladroit, j'aime le caractère explicite.
Winston Ewert
9
Je ne vois pas quel est le problème avec le moi explicite. En C ++, Java et D, les gens rendent souvent les variables de membre explicites par convention de toute façon, par exemple en les préfixant avec un trait de soulignement.
Dsimcha
7
Vous utilisez self dans des méthodes différentes de leur déclaration: def foo (self) mais self.foo (). Je trouve ce mélange de définition explicite mais implicite dans les coulisses pas trop joli.
LennyProgrammers
4

Mes reproches à propos de Python:

  • POOP boulonné (Voir la réponse de @ mipadi pour plus de précisions à ce sujet)
  • Mise en œuvre brisée de lambdas
  • Problèmes de portée
  • Pas de collections persistantes dans la bibliothèque standard
  • Mauvaise disponibilité des DSL intégrés
manquantfaktor
la source
Pourquoi le vote négatif?
missingfaktor
Je ne suis pas le votant inférieur, mais pouvez-vous expliquer pourquoi vous pensez que l'OO est bloqué? Python a toujours eu OO, c'est une partie essentielle du langage.
Daenyth
Voir la réponse de @ mipadi.
missingfaktor
4

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 .

Mikey
la source
Donc, le manque de contrôles d'accès est mauvais ... mais l'étendue explicite des écritures variables dans un espace de noms non local est également mauvaise?
ncoghlan
@ncoghlan: 1 - cette fonctionnalité est standard dans de nombreuses langues modernes, en fonction de la configuration de votre projet. 2 -Il est sous le contrôle du programmeur. 3 - je ne sais pas ce qui est formidable à ce sujet - vous pouvez facilement contrôler votre portée avec quelques paramètres de projet dans la plupart des langages / IDE compilés. Si «nous sommes tous des adultes consentants», nous devrions être en mesure de prendre nos propres décisions et d'adapter la portée en fonction de notre niveau de confort particulier.
Vecteur le
2
Le fait est que les personnes qui demandent des "contrôles d’accès imposés" nous demandent de supprimer l’un des éléments qui font de Python un si bon langage: il est délibérément difficile pour les développeurs de contrôler la manière dont leur code sera utilisé ultérieurement. Quelle proportion de la passe-partout dans les modèles C ++ et Java existe-t-elle uniquement pour contourner les contrôles d'accès imposés? Je peux certainement comprendre que les gens choisissent de ne pas utiliser Python pour ces raisons, mais l’application statique ne remplacera jamais des tests rigoureux.
ncoghlan
1
@ncoghlan - Pour moi, les points forts de Python sont l'élégance de la syntaxe et la brièveté - l'expressivité. Et comme je l'ai dit, la portée a moins à voir avec les programmeurs jouant avec des choses qu'ils ne devraient pas faire qu'avec la structure et l'organisation du code - le concept de «adultes consentants» est donc discutable. Je travaille sur des projets complexes, et non sur de simples utilitaires et scripts - le code doit être soigneusement structuré et structuré - les modificateurs d'accès sont l'un des moyens les plus importants de le garantir.
Vecteur
1
Et l'examen du code, la formation et l'analyse de couplage en sont d'autres. Pour moi, les contrôles d’accès imposés tombent dans le même panier que le typage statique: ils contribuent à renforcer la confiance en la précision (mais pas suffisamment pour éviter la nécessité de tests approfondis), mais à un coût élevé en productivité de développement. (Au niveau pratique, les contrôles d'accès aux attributs de classe ne correspondent pas non plus au modèle d'objet de Python, dans lequel les méthodes ne sont que des fonctions ordinaires extraites de classes. La limite "intérieur / extérieur" des classes n'existe pas. forcé)
ncoghlan
3
  1. La performance n’est pas bonne, mais elle s’améliore avec pypy,
  2. Le GIL empêche l’utilisation du threading pour accélérer le code (bien qu’il s’agisse généralement d’une optimisation prématurée),
  3. Ce n'est utile que pour la programmation d'applications,

Mais il a quelques fonctionnalités intéressantes:

  1. C'est parfait pour RAD,
  2. Il est facile de s’interfacer avec C (et pour que C intègre un interpréteur python),
  3. C'est très lisible,
  4. C'est facile à apprendre,
  5. C'est bien documenté,
  6. Les piles sont vraiment incluses, sa bibliothèque standard est énorme et pypi contient des modules pour pratiquement tout,
  7. Il a une communauté en bonne santé.
dan_waterworth
la source
Qu'est-ce qui a motivé à mentionner les avantages? La question pour les problèmes. Quoi qu'il en soit, que voulez-vous dire par ce qui est utile uniquement pour la programmation d'applications? Quelle autre programmation existe-t-il? A quoi sert-il pas spécifiquement?
Tshepang
5
J'ai énuméré les avantages parce que je pense qu'ils l'emportent sur les inconvénients. Avez-vous déjà essayé d'implémenter un module de noyau Linux en python?
dan_waterworth
3

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.

Niklas Rosencrantz
la source
1
Vous voudriez éditer sérieusement le code C ou Java pour changer le niveau de blocage de certains codes sans changer leur retrait?
Ben
4
@Ben Temporairement, oui ...
alternative le
1
@bien pareil ici.
Christopher Mahan
2
J'utilise le truc de changer if something()pour if False and something(). Une autre astuce consiste à "commenter" à l'aide d'une chaîne de plusieurs lignes.
Martin Vilcans
1
@ Martin Bien sûr! si faux ...
Christopher Mahan
3

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 dlopenun accès collectif au système de fichiers.

Jed
la source
Wow, semble très technique, avez-vous des documents de référence, des exemples, des billets de blog ou des articles sur le sujet? Je me demande si je pourrais être exposé à de tels cas dans un proche avenir.
Vincent le
Aron a donné une conférence à SciPy 2012 . Le contenudlopen 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.
Jed
3
  • un bon nombre de bibliothèques et de logiciels tiers très répandus et largement utilisés ne sont pas du tout pythoniques. Quelques exemples: soaplib, openerp, reportlab. La critique est hors du champ, elle existe, elle est largement utilisée, mais elle rend la culture python confuse (cela fait mal à la devise qui dit "Il devrait y avoir un - et de préférence un seul moyen - évident de le faire"). Les succès pythoniques connus (tels que django ou trac) semblent être l'exception.
  • la profondeur potentiellement illimitée de l'abstraction de l'instance, classe, métaclasse est conceptuellement belle et unique. Mais pour le maîtriser, vous devez connaître en profondeur l'interprète (dans quel ordre le code python est interprété, etc.). Il n'est pas largement connu et utilisé (ou utilisé correctement), alors qu'une magie noire similaire, telle que les génériques C #, conceptuellement plus compliquée (IMHO) semble plus largement connue et utilisée, proportionnellement.
  • Pour bien comprendre la mémoire et le modèle de thread, vous devez être assez expérimenté en python, car il n’existe pas de spécifications complètes. Vous savez simplement ce qui fonctionne, peut-être parce que vous avez lu les sources de l'interprète ou des bizarreries expérimentées et que vous avez découvert comment les résoudre. Par exemple, il n'y a que des références fortes ou faibles, pas les références douces et fantômes de Java. Java a un fil pour la récupération de place alors qu'il n'y a pas de réponse officielle sur le moment où la récupération de place a lieu en python; vous pouvez simplement observer que la récupération de place ne se produit pas si aucun code python n'est exécuté, et en conclure que cela se produit parfois lorsque vous essayez d'allouer de la mémoire. Cela peut être délicat lorsque vous ne savez pas pourquoi une ressource verrouillée n'a pas été publiée (mon expérience à ce sujet était mod_python dans freeswitch).

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.

vincent
la source
+1 Spec pour la mémoire et le modèle de threading est juste. Mais FWIW, le ramasse-miettes Java se trouvant sur un thread (et presque tout le reste à propos du GC) n'est pas un aspect du langage Java ni des spécifications de la VM, mais relève de la mise en œuvre d'une JVM particulière. Cependant, la JVM principale Sun / Oracle est largement documentée sur le comportement et la configurabilité du GC, dans la mesure où des livres entiers sont publiés sur le réglage de la JVM. En théorie, on pourrait documenter CPython de la même manière, quelle que soit la langue utilisée.
Andrew Janke
2
  • Etrange POO:
    • len(s)à travers __len__(self)et autres "méthodes spéciales"
    • méthodes spéciales spéciales pouvant être dérivées d'autres méthodes spéciales ( __add__et __iadd__pour +et +=)
    • self comme premier paramètre de méthode
    • vous pouvez oublier d'appeler le constructeur de la classe de base
    • pas de modificateurs d'accès (privé, protégé ...)
  • pas de définitions constantes
  • aucune immuabilité pour les types personnalisés
  • GIL
  • performances médiocres qui conduisent à un mélange de Python et de C et à des problèmes de construction (recherche de librairies C, dépendances de plate-forme, etc.)
  • mauvaise documentation, surtout dans les bibliothèques tierces
  • incompatibilité entre Python 2.x et 3.x
  • Outils d'analyse de code médiocres (comparés à ceux proposés pour les langages à typage statique tels que Java ou C #)
démon
la source
5
Personnellement, je pense que l'incompatibilité entre 2.x et 3.x est l'un des plus gros avantages de Python. Bien sûr, c'est aussi un inconvénient. Mais l'audace des développeurs à briser la compatibilité en amont signifie également qu'ils n'ont pas à se débrouiller sans fin. Plus de langues ont besoin d'une telle refonte.
Konrad Rudolph
0

"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.))

Kosta
la source
0

J'aimerais avoir explicitement des constructions parallèles. Le plus souvent, quand j'écris une liste de compréhension comme

[ f(x) for x in lots_of_sx ]

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.

Rbanffy
la source
// spawn bunch of threads // passe la file d'attente que à tous les threads que.extend ([x pour x dans lots_of_sx]) que.wait () # Attend que tous les lots_of_sx soient traités par les threads.
Zoran Pavlovic
0

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).

a3nm
la source