7
votes

Comment se protéger contre les fautes de frappe lors de la réglage de la valeur des membres de la classe?

Considérez l'exemple suivant:

>>> s = "lol"
>>> s.a = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'a'


5 commentaires

Vous pourriez avoir de meilleures réponses si vous expliquez également pourquoi vous voulez faire cela.


Tentatives de transformer Python en Java / C ++ m'a toujours perplexe de la même manière que le singleton anti-motif le fait. Si vous ne voulez pas plus d'un foo, ne l'instanciez pas, si vous ne voulez pas a.y ne le lie pas. Si vous voulez contraindre votre utilisateur de la bibliothèque de manière mystérieuse, vous faites quelque chose de mal.


Ok, ce n'est probablement pas ce que je veux vraiment. Le problème est que les objets d'une classe sont utilisés dans de nombreux lieux de code et membre "A" a une importance haghère. Disons que c'est un vrai nom est "Superimportantsession". Dans le cas de la faute de la typographie dans un lieu de code et a écrit «A.SuperimportantsSsssssion = 1», je n'aurai aucune erreur lorsque cette ligne de code sera exécutée. Mais je vais m'amuser du temps pour déboguer l'erreur. Je dois probablement utiliser des ensembles / greau ou de la smth comme ça.


En tout mon temps en utilisant Python, je n'ai jamais eu un problème de débogage difficile à déboguer à la suite d'un nom de nom d'attribut. C'est un problème de croire: les personnes habituées à d'autres langues pensent que c'est un problème énorme, mais ce n'est vraiment pas.


Après avoir souffert de cette question, laissez-moi vous assurer que c'est pas croire. Pour moi, l'astuce consistait à sélectionner une convention de dénomination, N'oubliez pas Mon choix et tenez-vous avec elle.


3 Réponses :


7
votes

Vous pouvez remplacer __setattr__ pour permettre uniquement les noms d'attributs d'un Liste définie.

>>> a = A()
>>> a.x = 5
>>> a.other = 5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "myc.py", line 7, in __setattr__
    raise AttributeError('No attribute: %s' % name)
AttributeError: No attribute: other   


4 commentaires

Convenu avec des tests d'unités, mais est-ce vraiment le meilleur moyen d'éviter les fautes de frappe?


Une combinaison de tests unitaires et d'autres types de tests automatisés. par exemple. En utilisant votre exemple des commentaires sur la question elle-même, s'il y avait un test qui a vérifié l'état de votre session avant et après une opération, vous seriez en mesure de dire si Superimportants n'avait pas été réglé correctement.


@Stipa: Je le dirais, comme vous devriez faire deux mêmes fautes de frappe. Quelque chose comme la faute de frappe lors de la déclaration variable et du setter.


Il y a beaucoup de cas où il est très utile que le code de l'utilisateur puisse assigner des attributs arbitraires aux classes, sans que la classe elle-même soignée d'eux. Cela briserait cela sans raison. N'oubliez pas non plus que cela ne fera que rien attraper à l'exécution, pas de compilation. Ne faites pas cela à moins d'avoir une raison spécifique à.



3
votes

Vous pouvez définir une variable de classe appelée __ Slots __ . Voir le Référence de langue pour plus d'informations.

__ Slots __ < / Code> Ne travaillez que dans les classes de style neuf, vous avez donc besoin de de classe A (objet) au lieu de de classe A dans cet exemple. xxx < / pré>


1 commentaires

__ Slots __ Pour une optimisation de la mémoire et devrait être utilisé très rarement. L'utilisation de la "protection contre les fautes de frappe" est une mauvaise utilisation - s'il vous plaît ne le recommandez pas à cette fin. Les novices ne comprendront pas ce qu'ils brisent - par exemple, cela a brisé silencieusement les faiblesses.



2
votes

Le meilleur moyen de protéger contre les typos consiste à utiliser un outil tel que pyflakes ou pylint - Celles-ci iront dans votre code et vous permettront savoir si vous avez une variable a. SuperimportantsesssssSionnnnnnnnn qui n'est plus jamais utilisé, ainsi que de nombreuses autres choses.

Si vous insistez pour le faire en code, vous avez deux options:

  • (AB) Utilisez __ Slots __ - L'objectif principal de __ slots __ est une optimisation de la mémoire pour ces moments où vous aurez des centaines, des milliers ou des millions d'objets Et vous devez garder les empreintes de vos objets aussi petits que possible. Si vous allez à cet itinéraire, vous devez vous assurer et inclure __ faimRef __ comme l'un des noms autorisés de sorte que Les références faibles continueront de travailler.

  • (AB) Utilisez __ SETATTR __ - L'objectif principal de __ setattr __ est de permettre à COD code d'exécuter pour valider, manipuler ou prendre autrement les données données. et mettez-le dans le bon format pour le stockage

    Pour réitérer, les deux options ci-dessus ne sont pas destinées à être utilisées comme dames orthographiques, ainsi que vos efforts pour limiter l'utilité de votre code en désactivant chaque nom d'attribut possible, à l'exception de ces rares que vous utilisez vous-même peut ne pas être apprécié quand quelqu'un essaie de soutenir un cas d'utilisation que vous n'avez pas anticipé.


0 commentaires