Question

Il existe des outils d'analyse statique pour Python , mais les vérifications de temps de compilation tendent à être diamétralement opposées à la liaison au moment de l'exécution philosophie que Python embrasse. Il est possible d’envelopper l’interpréteur Python standard avec un outil d’analyse statique pour imposer certaines "& a; utiliser des contraintes strictes , mais nous ne voyons aucune adoption généralisée d'une telle chose.

Y a-t-il quelque chose à propos de Python qui rend "use strict"? comportement inutile ou particulièrement indésirable?

Sinon, est-ce que le " use strict " comportement inutile en Perl, malgré son adoption généralisée?

Remarque: Par "nécessaire". Je veux dire "pratiquement nécessaire", pas strictement nécessaire. Évidemment, vous pouvez écrire Perl sans utiliser "strict", " mais (d'après ce que j'ai vu) la plupart des programmeurs Perl l'utilisent .

Remarque: l'interpréteur-wrapper Python n'a pas besoin de demander "d'utiliser des contraintes strictes - vous pouvez utiliser un pseudo-pragma similaire à" use strict ". cela serait ignoré par l'interprète normal. Je ne parle pas d'ajouter une fonctionnalité de niveau de langue.

Mise à jour: explication de ce que "& use; strict". fait en Perl par commentaires. (Le lien vers les documents officiels se trouve dans le premier paragraphe.)

Le " use strict " La directive a trois composantes distinctes, dont seulement deux sont vraiment intéressantes:

  • utilise des variables strictes: vérifie de manière statique l'utilisation des variables à portée lexicale dans votre programme. (N'oubliez pas qu'en Python, il n'y a fondamentalement que les domaines global et local ). Beaucoup de linters Python vérifient ce genre de chose. S'agissant de la seule analyse statique qu'ils peuvent effectuer, les linters supposent que vous utilisez une définition lexicale directe et vous avertissent des choses qui semblent erronées dans ce sens jusqu'à ce que vous leur disiez de vous taire; c'est-à-dire

    FOO = 12
    foo += 3
    

    Si vous ne faites rien d'extraordinaire avec vos espaces de noms, cela peut être utile pour vérifier les fautes de frappe.

  • use strict refs: Empêche la déréférencement des espaces de noms symboliques. L'analogue le plus proche de Python utilise locals () et globals () pour effectuer une liaison symbolique et une recherche d'identifiant.

  • utiliser des sous-marins stricts: aucun analogique réel en Python.

Était-ce utile?

La solution

"La philosophie de liaison au moment de l'exécution adoptée par Python ... permet à" d'utiliser "strict". comportement inutile [et] particulièrement indésirable "

Très bon résumé. Merci.

C'est essentiellement ça. Les outils d'analyse statique n'aident pas suffisamment Python pour en valoir la peine.

Modifier

"Je demande que nous examinions pourquoi nous n'en avons pas besoin et, parallèlement, pourquoi les programmeurs Perl pensent en avoir besoin."

La raison en est précisément la raison que vous avez déjà donnée. Nous n'en avons pas besoin parce que ça n'aide pas. De toute évidence, vous n’aimez pas cette réponse, mais il n’ya pas grand chose à dire. La vérification au moment de la compilation ou de la pré-compilation n'aide tout simplement pas.

Cependant, puisque vous avez pris le temps de poser la question à nouveau, je vais fournir davantage d'éléments de preuve pour la réponse que vous avez déjà donnée.

J'écris presque autant en Java qu'en Python. La vérification de type statique de Java n'empêche aucun problème de logique; cela ne facilite pas le respect des exigences de performance; cela n'aide pas à répondre aux cas d'utilisation. Cela ne réduit même pas le volume de tests unitaires.

Bien que la vérification de type statique ne détecte pas le mauvais usage occasionnel d'une méthode, vous le découvrez aussi rapidement en Python. En Python, vous le trouvez au moment du test de l'unité, car il ne fonctionnera pas. Remarque: je ne dis pas que des types incorrects sont trouvés avec de nombreux tests unitaires astucieux, je dis que la plupart des problèmes de types incorrects se rencontrent via des exceptions non gérées, où la tâche ne peut tout simplement pas aller assez loin pour pouvoir tester des assertions.

La raison pour laquelle les pythonistes ne perdent pas de temps en vérification statique est simple. Nous n'en avons pas besoin. Il n'offre aucune valeur. C'est un niveau d'analyse qui ne présente aucun avantage économique. Cela ne me permet plus de résoudre les vrais problèmes que rencontrent de vraies personnes avec leurs données réelles.

Consultez les questions SO Python les plus courantes qui sont liées à la langue (pas au domaine ou à la bibliothèque qui pose problème).

Existe-t-il une différence entre " foo n'est pas " et "foo == Aucun" - == vs. est . Aucune vérification statique ne peut aider à cela. Voir aussi Y a-t-il une différence entre `==` et ` is` en Python?

Que font ** (étoile double) et * (étoile) pour parameters? - * x donne une liste, ** x donne un dictionnaire. Si vous ne le savez pas, votre programme meurt immédiatement lorsque vous essayez de faire quelque chose d'inapproprié pour ces types. "Et si votre programme ne fait jamais rien" inapproprié "&"; " Ensuite, votre programme fonctionne. 'Nuff a dit.

Comment puis-je représenter un "Enum" dans Python? - C’est un plaidoyer pour une sorte de type de domaine limité. Une classe avec des valeurs de niveau fait assez bien ce travail. "Et si quelqu'un modifiait la mission". Facile à construire. Remplacez __ set __ pour déclencher une exception. Oui, la vérification statique pourrait repérer ceci. Non, dans la pratique, il n'arrive pas que quelqu'un s'embrouille au sujet d'une constante d'énumération et d'une variable; et quand ils le font, il est facile de les repérer au moment de l'exécution. "Que se passe-t-il si la logique n'est jamais exécutée". Eh bien, c'est une mauvaise conception et des tests unitaires médiocres. Lancer une erreur du compilateur et insérer une mauvaise logique qui n'a jamais été testée n'est pas mieux que ce qui se passe dans un langage dynamique quand elle n'est jamais testée.

Expressions du générateur et compréhension de la liste - la vérification statique n'aide pas à résoudre cette question.

Pourquoi 1 +++ 2 = 3? - statique vérifier ne serait pas repérer cela. 1 +++ 2 en C est parfaitement légal malgré toutes les vérifications du compilateur. Ce n'est pas la même chose en Python et en C, mais tout aussi légal. Et tout aussi déroutant.

Liste des modifications de liste reflétées de manière inattendue dans les sous-listes - - Ceci est entièrement conceptuel. La vérification statique ne peut pas aider à résoudre ce problème non plus. L’équivalent Java compilerait et se comporterait mal.

Autres conseils

Eh bien, je ne suis pas un grand programmeur python, mais je dirais que la réponse est "OUI".

Tout langage dynamique permettant de créer une variable avec un nom à tout moment peut utiliser un pragma "strict".

Les codes strict (une des options pour strict dans Perl, "use strict" les active tous en même temps). En Perl, toutes les variables sont déclarées avant leur utilisation. Ce qui signifie que ce code:

my $strict_is_good = 'foo';
$strict_iS_good .= 'COMPILE TIME FATAL ERROR';

Génère une erreur fatale lors de la compilation.

Je ne connais pas de moyen de faire en sorte que Python rejette ce code lors de la compilation:

strict_is_good = 'foo';
strict_iS_good += 'RUN TIME FATAL ERROR';

Vous obtiendrez une exception d'exécution selon laquelle strict_iS_good n'est pas défini. Mais seulement lorsque le code est exécuté. Si votre suite de tests ne couvre pas 100%, vous pouvez facilement envoyer ce bogue.

Chaque fois que je travaille dans une langue qui n’a pas ce comportement (PHP par exemple), je suis nerveux. Je ne suis pas un dactylographe parfait. Une faute de frappe simple, mais difficile à repérer, peut entraîner l'échec de votre code, ce qui peut être difficile à localiser.

Ainsi, pour réitérer, OUI , Python pourrait utiliser un pragma "strict" pour activer la vérification de la compilation des éléments pouvant être vérifiés au moment de la compilation. Je ne peux penser à aucune autre vérification à ajouter, mais un meilleur programmeur Python pourrait probablement en penser.

Remarque Je me concentre sur l'effet pragmatique des variables de conflit en Perl et je passe en revue certains détails. Si vous voulez vraiment connaître tous les détails, consultez le perldoc pour strict .

Mise à jour: réponses à certains commentaires

Jason Baker : Les vérificateurs statiques comme pylint sont utiles. Mais ils représentent une étape supplémentaire qui peut être et est souvent ignorée. Construire des vérifications de base dans le compilateur garantit que ces vérifications sont effectuées de manière cohérente. Si ces contrôles sont contrôlables par un pragma, même l'objection relative au coût des contrôles devient sans objet.

popcnt : Je sais que python générera une exception d'exécution. J'ai dit autant. Je préconise la vérification du temps de compilation lorsque cela est possible. Veuillez relire l'article.

mpeters : aucune analyse informatique du code ne permet de détecter toutes les erreurs - cela revient à résoudre le problème d'arrêt. Pire, pour trouver des fautes de frappe dans les assignations, votre compilateur aurait besoin de connaître vos intentions et de trouver les emplacements où vos intentions diffèrent de celles de votre code. C'est assez clairement impossible.

Cependant, cela ne signifie pas qu’aucune vérification ne doit être effectuée. S'il existe des classes de problèmes faciles à détecter, il est logique de les résoudre.

Je ne connais pas assez pylint et pychecker pour dire quelles classes d’erreurs ils vont intercepter. Comme je le disais, je suis très inexpérimenté avec Python.

Ces programmes d’analyse statique sont utiles. Cependant, je crois que sauf s’ils dupliquent les capacités du compilateur, celui-ci sera toujours en mesure de "connaître" les informations. plus sur le programme que n'importe quel vérificateur statique pourrait. Il semble inutile de ne pas en profiter pour réduire les erreurs autant que possible.

Mise à jour 2:

cdleary - En théorie, je suis d'accord avec vous, un analyseur statique peut effectuer toute validation que le compilateur peut effectuer. Et dans le cas de Python, cela devrait suffire.

Cependant, si votre compilateur est suffisamment complexe (surtout si vous avez beaucoup de pragmas qui changent la façon dont la compilation se déroule, ou si, comme Perl, vous pouvez exécuter du code au moment de la compilation), l'analyseur statique doit alors aborder la complexité du compilateur. / interprète pour faire l'analyse.

Hé, tout ce discours sur les compilateurs complexes et le code en cours au moment de la compilation montre mon arrière-plan Perl.

D'après ce que j'ai compris, Python n'a pas de pragmas et ne peut pas exécuter de code arbitraire au moment de la compilation. Ainsi, à moins que je ne me trompe ou que ces fonctionnalités ne soient ajoutées, un analyseur syntaxique relativement simple dans l’analyseur statique devrait suffire. Il serait certainement utile de forcer ces contrôles à chaque exécution. Bien sûr, je le ferais avec un pragma.

Une fois que vous avez ajouté des pragmas au mixage, vous avez démarré sur une pente glissante et la complexité de votre analyseur doit croître proportionnellement à la puissance et à la flexibilité que vous fournissez dans vos pragmas. Si vous ne faites pas attention, vous pouvez vous retrouver comme Perl, puis "seul Python peut analyser Python". un avenir que je ne voudrais pas voir.

Peut-être qu'un commutateur de ligne de commande serait un meilleur moyen d'ajouter une analyse statique forcée;)

(En aucun cas, n'entendez attaquer les capacités de Python quand je dis qu'il ne peut pas rester avec un comportement de compilation comme Perl le peut. Je suis persuadé qu'il s'agit d'une décision de conception minutieuse, et je peux voir la sagesse de La flexibilité extrême de Perl au moment de la compilation est, à mon humble avis, une grande force et une terrible faiblesse de la langue; je vois aussi la sagesse de cette approche.)

Python a quelque chose qui peut changer la syntaxe du script:

from __future__ import print_function

et diverses autres fonctionnalités futures ayant des implications sur la syntaxe. C'est simplement que la syntaxe de Python a été plus stricte, plus stable et plus bien définie que l'historique Perl; le genre de choses que les références strictes & # 8217; et & # 8216; sous-marins stricts & # 8217; interdire n’a jamais existé en Python.

& # 8216; vars strict & # 8217; est principalement destiné à empêcher les références typographiques et les informations manquées de créer des paramètres globaux accidentels (ainsi, les variables de package en termes Perl). Cela ne peut pas arriver en Python car les assignations nues sont définies par défaut en déclaration locale et les symboles nus non attribués génèrent une exception.

(Il existe toujours le cas où des utilisateurs tentent accidentellement d'écrire dans un global sans le déclarer avec une instruction & 8217; globale & # 8217; causant soit un accident local, soit le plus souvent un UnLocalError. Ceci tend à à apprendre assez rapidement, mais c’est un cas discutable dans lequel il serait utile de déclarer ses sections locales, même si peu de programmeurs Python expérimentés accepteraient le fardeau de la lisibilité.)

Les autres modifications de langue et de bibliothèque ne faisant pas appel à la syntaxe sont traitées via le système warnings . .

Je pense qu'il y a une certaine confusion en ce qui concerne l'utilisation "& strict". fait, à partir des commentaires que je vois. Il n'active pas les contrôles de type de compilation (pour ressembler à Java). En ce sens, les programmeurs Perl sont en accord avec les programmeurs python. Comme le dit S.Lott ci-dessus, ces types de vérifications ne protègent pas contre les bogues logiques, ne réduisent pas le nombre de tests unitaires que vous devez écrire et nous ne sommes pas non plus de grands fans de la programmation par esclavage.

Voici une liste de ce que vous utilisez & strict; strict " fait-il:

  1. L'utilisation de références symboliques est une erreur d'exécution. Cela vous empêche de faire des folies (mais parfois des choses utiles, par exemple)

    $ var = 'foo';

    $ foo = 'bar';

    print $$ var; # cela contiendrait le contenu de $ foo à moins d’être exécuté sous strict

  2. L'utilisation de variables non déclarées est une erreur d'exécution (cela signifie que vous devez utiliser "mon", "notre" ou "local" pour déclarer la portée de votre variable avant de l'utiliser.

  3. Tous les mots nus sont considérés comme des erreurs de syntaxe au moment de la compilation. Les mots nus sont des mots qui n'ont pas été déclarés en tant que symboles ou sous-routines. C’est principalement pour interdire quelque chose qui a été fait historiquement mais qui est considéré comme une erreur.

Python n’a pas de véritable portée lexicale, donc des règles strictes ne seraient pas très raisonnables. Il n'a pas de références symboliques autant que je sache, il n'a donc pas besoin de références strictes. Il n’a pas de mots simples, il n’a donc pas besoin de règles strictes.

Pour être honnête, ce n’est que la portée lexicale qui me manque. Les deux autres, je considérerais les verrues en Perl.

Cette réponse originale est correcte, mais n'explique peut-être pas la situation dans un sens pratique.

  

Il existe des outils d'analyse statiques pour Python, mais les contrôles de compilation ont tendance à être "diamétralement opposés" à la philosophie de liaison d'exécution adoptée par Python.

Ce que 'use strict' fournit en Perl, c’est la possibilité de s’assurer qu’un mal orthographié ou le nom de variable est (généralement) intercepté au moment de la compilation. Cela améliore le code fiabilité, et accélère le développement. Mais pour rendre une telle chose utile, vous devez déclarer des variables. Et le style Python semble décourager cela.

Donc, en Python, vous ne découvrez jamais une variable mal orthographiée tant que vous n’avez pas remarqué à l'exécution que la tâche que vous pensiez avoir n'est pas faite, ou qu'un expression semble se résoudre à une valeur inattendue. Attraper de telles erreurs peut être prend beaucoup de temps, en particulier à mesure que les programmes prennent de l'ampleur et que les gens sont obligés de maintenir code développé par d'autres.

Java et C / C ++ vont encore plus loin, avec la vérification de type. La motivation est pratique, plutôt que philosophique. Comment pouvez-vous intercepter le plus rapidement possible autant d'erreurs et vous assurer de les éliminer toutes avant de remettre le code en production? Chaque langue semble adopter une stratégie particulière et la suivre, en fonction de ce qu’elle penser est important. Dans un langage comme Perl, où la liaison au moment de l'exécution n'est pas prise en charge, il est logique de tirer parti de 'use strict' pour faciliter le développement.

Je considère le 'use strict' dans Perl plus comme un pragma, comme vous l'avez laissé entendre: cela change le comportement du compilateur.

La philosophie du langage Perl est différente de la philosophie python. Au fur et à mesure, vous disposez de suffisamment de corde pour vous pendre à plusieurs reprises, en Perl.

Larry Wall est un grand spécialiste de la linguistique, nous avons donc de Perl ce que l’on appelle le principe TIMTOWTDI (par exemple, tim-toe-dee ) par rapport au zen du langage python:

  

Il devrait y avoir one-- et de préférence   Une seule façon - évidente de le faire.

vous pouvez très facilement utiliser pylint et PyChecker pour créer votre propre version de use strict pour python (ou quelque chose d'analogue à perl -cw * scriptname * ), mais En raison des différentes philosophies dans la conception du langage, vous ne le rencontrerez pas largement dans la pratique.

En vous basant sur votre commentaire à la première affiche, vous connaissez bien importer ce de python. De nombreuses choses expliquent pourquoi vous ne voyez pas un équivalent de use strict en Python. Si vous méditez sur le koan trouvé dans le zen de Python, vous pourrez peut-être vous éveiller. :)

J'ai constaté que je ne tenais vraiment qu'à détecter les références aux vars non déclarés. Eclipse a une intégration de pylint via PyDev et, bien que pylint soit loin d’être parfait, il fait un travail raisonnable.

Cela va à l'encontre de la nature dynamique de Python, et je dois ajouter des #IGNORE à l'occasion, lorsque mon code devient intelligent à propos de quelque chose. Mais je trouve que cela se produit assez rarement pour que j'en sois heureux.

Mais je pouvais voir l'utilité de certaines fonctionnalités de type pylint devenant disponibles sous la forme d'un indicateur de ligne de commande. Un peu comme le commutateur -3 de Python 2.6, qui identifie les points d’incompatibilité entre le code Python 2.x et 3.x.

Il est très difficile d'écrire de gros programmes sans utiliser 'strict »en Perl. Sans 'use strict', si vous utilisez à nouveau une variable et que vous l'orthographiez mal en laissant une lettre, le programme est toujours exécuté. Et sans test cas pour vérifier vos résultats, vous ne pouvez jamais trouver de telles erreurs. Il peut être très fastidieux de découvrir pourquoi vous obtenez des résultats erronés pour cette raison.

Certains de mes programmes Perl comportent de 5 000 lignes à 10 000 lignes de code divisées en dizaines de modules. On ne peut pas vraiment faire de programmation de production sans 'use strict'. Je ne permettrais jamais l'installation de code de production en usine avec des langages qui n'appliquent pas les "déclarations de variables".

C'est pourquoi Perl 5.12.x a maintenant le comportement par défaut 'use strict'. Vous pouvez les désactiver.

PHP m’a posé pas mal de problèmes à cause de l’absence de déclaration de variable variable. Vous devez donc vous limiter aux petits programmes utilisant cette langue.

Juste un avis ...

abcParsing

Perl est un langage débridé comme ils l’ont dit :). Donc, vous pouvez utiliser la variable avant annoncé; Exemple: si vous utilisez un nom de variable " is_array " mais saisissez " is_arrby " , le compilateur ne signalera aucune erreur sans utiliser " strict " . Ainsi, lorsque vous codez un programme long en perl, il vaut mieux utiliser " use strict " déclaration. Bien sûr, moins de 50 lignes pour exécuter un script unique ne sont pas nécessaires :)

Cela semble être l'idéal de "Pythonic". le code a bien le même objectif que use strict .

Je n'ai pas d'expérience en Perl, mais d'après ce que je sais, aucune fonctionnalité en python ne doit être désactivée pour que votre code soit "plus fiable", alors, dans ce sens, vous pouvez dire que c'est inutile

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top