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)
13
demandé sur Decio Lira 2010-01-23 18:08:34

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'))
20
répondu Ignacio Vazquez-Abrams 2010-01-23 15:23:08

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.

5
répondu PaulMcG 2010-01-23 16:00:52
class...
 def __setattr__(self, name, value):
  print 'setting', name
  self.__dict__[name] = value

C'est ça.

2
répondu Tor Valamo 2010-01-23 15:20:23

peut-être que vous cherchez __setattr__(self, name, value)

regardez ici

1
répondu Keeper 2010-01-23 15:12:26