Pourquoi le paramètre « name » à __setattr__ comprennent la classe, mais __getattr__ ne fonctionne pas?

StackOverflow https://stackoverflow.com/questions/2386418

  •  24-09-2019
  •  | 
  •  

Question

Le code suivant:

class MyClass():
    def test(self):
        self.__x = 0

    def __setattr__(self, name, value):
        print name

    def __getattr__(self, name):
        print name
        raise AttributeError(name)

x = MyClass()
x.test()
x.__y

Sorties:

_MyClass__x
__y
Traceback (most recent call last):
...
AttributeError: __y

La documentation est tout à fait inutile indiquant le « nom » est le « nom de l'attribut », mais pour une raison quelconque, il est différent selon que vous définissez ou l'obtenir.

Ce que je veux savoir est:

  • Suis-je faire quelque chose de fondamentalement mauvais ici?
  • Comment puis-je obtenir x dans le premier cas au lieu de _MyClass__x?
Était-ce utile?

La solution

Le double underscore invoque le nom mutiler. Si vous n'avez pas besoin mangling nom, ne pas utiliser le double undescore

Quelle est la signification d'un simple et un double underscore avant un nom d'objet

De Python docs

  

9,6. Variables privées

     

exemple « privé » des variables qui ne sont pas accessibles, sauf à l'intérieur d'un objet, n'existent pas en Python. Cependant, il y a une convention qui est suivie par la plupart du code Python: un nom préfixé par un trait de soulignement (par exemple _spam) devraient être traités comme une partie non publique de l'API (si elle est une fonction, une méthode ou un membre de données) . Il doit être considéré comme un détail de mise en œuvre et sous réserve de modifications sans préavis.

     

Comme il y a un cas d'utilisation valable pour les membres de la classe-privé (à savoir pour éviter les conflits de noms de noms avec des noms définis par les sous-classes), il y a un soutien limité à un tel mécanisme, appelé nom mutiler. Tout identifiant de la forme __spam (au moins deux traits de soulignement, au plus un underscore final) est remplacé par textuellement _classname__spam, où classname est le nom de la classe actuelle avec underscore (s) dépouillé. Ce mangling se fait sans tenir compte de la position syntaxique de l'identifiant, tant qu'il se produit dans la définition d'une classe.

     

Notez que les règles de la plupart brouillage ont été dessinées pour éviter les accidents; il est toujours possible d'accéder ou de modifier une variable qui est considérée comme privée. Cela peut être utile même dans des circonstances particulières, comme dans le débogueur.

     

Notez que le code est passé à exec, eval() ou execfile() ne considère pas le nom de classe de la classe invocateur être la classe actuelle; ce qui est similaire à l'effet de la déclaration globale, dont l'effet est également limité au code qui est compilé en même temps. La même restriction se rapporte à getattr(), setattr() et delattr(), ainsi que lors du référencement directement __dict__.

Autres conseils

Je ne sais pas exactement pourquoi cela se produit, mais si vous utilisez _x plutôt que __x il fonctionne comme on peut s'y attendre.

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