web-dev-qa-db-fra.com

Portées variables dans les classes python

déclarer une variable dans une classe (en dehors d'une fonction): toutes les fonctions de la classe peuvent y accéder (essentiellement une variable publique)

déclarer une variable à l'intérieur d'une fonction à l'intérieur d'une classe: seule cette fonction peut y accéder (c'est dans la portée de cette fonction)

déclarer une variable avec self. (nom de variable) dans une fonction dans une classe: toutes les fonctions de classe peuvent y accéder (en quoi est-ce différent du global (nom de variable)?)

et comme il n'y a pas de privé/protégé, tout est public, donc tout ce qui est accessible de l'intérieur d'une classe est accessible de l'extérieur.

Y a-t-il d'autres nuances que je devrais connaître ou est-ce que je les ai bien comprises?

35
jason

Comme la liste de votre question n'est pas claire à 100%, j'ai décidé de l'expliquer avec un exemple simple. Il inclut également des éléments tels que les variables __something que vous n'avez pas mentionnées dans votre liste.

class Test:
    a = None
    b = None

    def __init__(self, a):
        print self.a
        self.a = a
        self._x = 123
        self.__y = 123
        b = 'meow'

Au début, a et b sont uniquement des variables définies pour la classe elle-même - accessibles via Test.a et Test.b et non spécifiques à une instance.

Lors de la création d'une instance de cette classe (ce qui entraîne l'exécution de __init__):

  • print self.a ne trouve pas de variable d'instance et renvoie donc la variable de classe
  • self.a = a: une nouvelle variable d'instance a est créée. Ceci occulte la variable de classe afin que self.a fasse maintenant référence à la variable d'instance; pour accéder à la variable de classe, vous devez maintenant utiliser Test.a
  • L'affectation à self._x crée une nouvelle variable d'instance. Il est considéré comme "ne faisant pas partie de l'API publique" (c'est-à-dire protégé) mais techniquement, il n'a pas de comportement différent.
  • L’affectation à self.__y crée une nouvelle variable d’instance nommée _Test__y, c’est-à-dire que son nom est mutilé, de sorte que vous ne pouvez y accéder que si vous utilisez le nom mutilé. Cela pourrait être utilisé pour les variables "privées".
  • L'affectation à b crée une variable locale. Il n'est pas disponible ailleurs que dans la fonction __init__ car il n'est pas enregistré dans l'instance, la classe ou la portée globale.
92
ThiefMaster

Déclarer une variable au plus haut niveau de la classe revient à déclarer une variable statique ou une variable de classe. La qualifier avec self, c'est déclarer une variable d'instance. Les variables de classe peuvent être modifiées en s'y référant par nom de classe (par exemple Class.x = 5) et toutes les instances hériteront de ces modifications. Les variables d'instance sont privées d'une instance et ne peuvent être modifiées que par cette instance.

Vous pouvez atteindre un certain niveau de contrôle d'accès à l'aide de traits de soulignement. Voir variables privées dans le tutoriel Python . Par convention, les variables commençant par un trait de soulignement, par exemple _foo sont des parties non publiques d'une API et les noms commençant par deux caractères de soulignement, par exemple. __foo aura comme nom mangled pour être _classname__foo.

20
Rafe Kettler

Bien que répondu, laissez-moi ajouter quelques commentaires à vos questions:

déclarer une variable dans une classe (en dehors d'une fonction): toutes les fonctions de la classe peuvent y accéder (essentiellement une variable publique): comment: cela ressemble à une variable statique et peut être appelé à l'aide du nom de la classe. Ces variables sont disponibles pour toutes les fonctions. Toutes les fonctions peuvent la modifier et l’imprimer.

déclarer une variable à l'intérieur d'une fonction à l'intérieur d'une classe: seule cette fonction peut y accéder (sa portée dans cette fonction): commentaire: si la variable est déclarée sans self, elle n'est accessible qu'à l'intérieur de cette fonction, c'est plutôt une variable locale. Cependant, s'il a déclaré en utilisant self comme self.var = 'somevalue' , alors il est accessible via n'importe quel objet mais pas via le nom de la classe.

déclarer une variable avec self. (nom de variable) dans une fonction dans une classe: toutes les fonctions de classe peuvent y accéder (en quoi cela diffère-t-il de global (nom de variable)?): comment: voir asnswer dans la partie ci-dessus.

et comme il n'y a pas de privé/protégé, tout est public, donc tout accessible de l'intérieur d'une classe est accessible de l'extérieur de la classe.:comment: oui, mais nous pouvons utiliser un trait de soulignement simple pour dire au monde que cette variable est privée mais techniquement cela ne le rend pas réellement privé.

0
Haris Muzaffar