2010-10-26 29 views
0

J'ai une question sur voie droite de la programmation en Python ... Peut-être qu'il peut y avoir plusieurs opinions différentes, mais ici il va:Accès à des variables privées quand il y a un getter/setter pour les

Disons que j'ai classe avec quelques attributs privés et que je l'ai mis en place deux getters/setters (pas le surchargement __getattr__ et __setattr__, mais dans un style plus « Java-tistic »):

class MyClass: 

    def __init__(self): 
     self.__private1 = "Whatever1" 

    def setPrivate1(self, private1): 
     if isinstance(private1, str) and (private1.startswith("private")): 
      self.__private1 = private1 
     else: 
      raise AttributeError("Kaputt") 

    def getPrivate1(self): 
     return self.__private1 

maintenant, disons quelques lignes ci-dessous, dans une autre méthode de la même classe, je dois redéfinir la valeur de ce "_ private1". Comme c'est la même classe, j'ai toujours un accès direct à l'attribut privé self. _private1.

Ma question est: Dois-je utiliser:

self.setPrivate1("privateBlaBlaBla") 

ou devrais-je accéder directement:

self.__private1 ="privateBlaBlaBla" 

depuis que je suis celui définissant la nouvelle valeur, je sais que ladite valeur (« privateBlaBlaBla ") est correct (un str() qui commence par" private "), donc il ne va pas laisser le système incohérent. D'un autre côté, si un autre programmeur prend mon code, et doit changer la fonctionnalité de l'attribut self .__ private1, il devra parcourir tout le code, et voir si la valeur de __private1 a été définie manuellement ailleurs. Je pense que la bonne chose à faire est de toujours utiliser la méthode setPrivate1, et d'accéder directement à la variable __private1 dans le get/set, mais j'aimerais connaître l'opinion des programmeurs Python plus expérimentés.

Merci!

+0

Le changement de nom de '__' ne fonctionne pas très bien. –

Répondre

6

Vous ne pouvez pas présenter un exemple classique de mauvaise Python, puis attendre les gens d'avoir des opinions sur ce faire à ce sujet . Utilisez des getters et des setters.

class MyClass: 
    def __init__(self): 
     self._private1 = "Whatever1" 

    @property 
    def private1(self): 
     return self._private1 

    @private1.setter 
    def private1(self, value): 
     self._private1 = value 

Un commentaire côté - en utilisant des noms de double underscore peut être source de confusion, parce que Python mutile en fait le nom pour vous empêcher d'y accéder à partir de l'extérieur de la classe. Cela ne fournit aucune sécurité réelle, mais ne cause pas de mal de tête. Le moyen le plus simple d'éviter les maux de tête est d'utiliser des noms de soulignement unique, ce qui est fondamentalement une convention universelle pour private. (Ish.)


Si vous voulez un avis - utiliser des propriétés =). Si vous voulez un avis sur votre monstruosité JavaPython, je voudrais utiliser le setter - après tout, vous l'avez écrit, c'est ce qu'il est là pour! Il n'y a aucun avantage évident à régler la variable à la main, mais il y a plusieurs inconvénients.

+0

+1 Deux de ces inconvénients sont: (1) vous devez taper cette monstruosité dont le nom est mangé et (2) il peut introduire des bogues subtils si le setter commence à faire un travail important dans le futur. – delnan

+0

C'est très cool, et c'est quelque chose auquel je n'avais pas prêté attention mais ça ne semble pas fonctionner avec python 2.4 (la partie setter) même si j'étend ma classe de "object" (fonctionne bien avec 2.6, cependant) – BorrajaX

+0

@BorrajaX: Dans Python2.4, utilisez 'private1 = propriété (getx, setx)', où 'getx' est la fonction getter et' setx' est le setter. Voir http://docs.python.org/library/functions.html#property – unutbu

2

Aucune. In Python, use properties, pas des getters et des setters.

class MyClass: 

    def __init__(self): 
     self._private1 = "Whatever1" 
    @property 
    def private1(self): 
     return self._private1 
    @private1.setter 
    def private1(self, private1): 
     if isinstance(private1, str) and (private1.startswith("private")): 
      self._private1 = private1 
     else: 
      raise AttributeError("Kaputt") 

Puis, plus tard dans votre code, définissez l'attribut _private1 avec

self.private1="privateBlaBlaBla"