Python: propriétés multiples, un setter / getter
considérer les définitions de classe suivantes
class of2010(object):
def __init__(self):
self._a = 1
self._b = 2
self._c = 3
def set_a(self,value):
print('setting a...')
self._a = value
def set_b(self,value):
print('setting b...')
self._b = value
def set_c(self,value):
print('setting c...')
self._c = value
a = property(fset=self.set_a)
b = property(fset=self.set_b)
c = property(fset=self.set_c)
notez que set_[a|b|c]()
fait la même chose. est-il un moyen de définir:
def set_magic(self,value):
print('setting <???>...')
self._??? = value
une fois et l'utiliser pour a,b,c comme suit:
a = property(fset=self.set_magic)
b = property(fset=self.set_magic)
c = property(fset=self.set_magic)
4 réponses
def attrsetter(attr):
def set_any(self, value):
setattr(self, attr, value)
return set_any
a = property(fset=attrsetter('_a'))
b = property(fset=attrsetter('_b'))
c = property(fset=attrsetter('_c'))
je vois que vos setters logent juste un message et puis assignent simplement la valeur - en fait, votre réponse acceptée juste assigne la valeur. Utilisez-vous ce modèle parce qu'il est la pratique acceptée / sagesse conventionnelle dans une autre langue, peut-être un dont le nom commence par "J"? Si c'est le cas, alors s'il vous plaît apprenez que l'approche pythonique de ce même design est beaucoup plus simple:
class Of2010(object):
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
Aucun ne rien faire setters, pas d'intermédiaire fonction appelle juste pour assigner une valeur. "Quoi?!", dites-vous? "L'exposition du Public aux variables de membre?!!"Eh bien, Oui en fait.
regardez ces classes du point de vue du code client. Pour utiliser votre classe, les clients créent un objet, puis assignent la propriété "a" en utilisant:
obj = Of2010()
obj.a = 42
remarquablement, c'est exactement le même code pour la classe de 5-liner I affichée ci-dessus.
Pourquoi le J-langue encourager le style de propriété plus verbeux? Préserver l'interface de classe en cas de changement futur des exigences. Si à un moment donné, une autre valeur de l'objet doit changer en même temps que toute modification de a, alors vous devez implémenter le mécanisme de propriété. Malheureusement, le J-language expose la nature du mécanisme d'accès aux attributs au code client, de sorte que d'introduire une propriété à un moment donné dans le futur est une tâche de remaniement intrusif qui nécessitera une reconstruction de tous les clients qui utilisent cette classe et son attribut" a".
en Python, tel n'est pas le cas. L'accès à l'attribut "a" de l'objet est déterminé à l'exécution dans l'appelant. Comme l'accès direct et l'accès à la propriété ont tous les deux la même apparence, votre classe Python préserve cette interface même si le mécanisme actuel est différent. Ce qui importe, c'est qu'il soit identique en ce qui concerne le code client.
donc en Java, on introduit cette propriété complexité dès le début de cette classe (et en fait, par la pratique acceptée, de toutes les classes ), au hasard qu'elle puisse devenir nécessaire un jour dans le futur. Avec Python, on peut commencer par implémenter la chose la plus simple qui pourrait éventuellement fonctionner, c'est-à-dire un accès direct à des variables membres simples, laissant l'approche complexe pour le temps dans le futur que les choses supplémentaires sont réellement nécessaires et de valeur. Depuis ce jour ne peut jamais revenir, c'est un énorme allez de l'avant pour faire sortir la première version de votre code.
class...
def __setattr__(self, name, value):
print 'setting', name
self.__dict__[name] = value
C'est ça.