2017-09-16 3 views
-1

Avant que cela ne soit marqué comme doublon, je connais ce question has been answered avant, mais les solutions fournies ici ne semblent pas s'appliquer à mon cas. J'essaye de programmer des propriétés de classe. Je sais que je peux utiliser property pour cela, donc je pensais à faire:Propriété de classe retournant l'objet de propriété

class Foo: 
    def __init__(self, x): 
     self._x = x 
     def getx(): return self._x 
     def setx(y): self._x = y 
     self.x = property(fget=getx, fset=setx) 

Cependant, quand je lance cette façon interactive, je reçois:

>>> f = Foo(42) 
>>> f.x 
<property object at 0x0000000> 
>>> f._x 
42 
>>> f.x = 1 
>>> f.x 
1 

est-il un moyen de résoudre ce problème?

Edit:

Je sens que je peux avoir laissé trop, alors voici ce que je suis en train d'essayer d'atteindre. J'ai une classe avec une variable de classe appelée config, qui contient des valeurs de configuration à définir en tant que propriétés. La classe doit être sous-à mettre en œuvre la variable config:

class _Base: 
    config =() 

    def __init__(self, obj, **kwargs): 
     self._obj = obj() 
     for kwarg in kwargs: 
      # Whatever magic happens here to make these properties 

# Sample implementation 
class Bar(_Base): 
    config = (
     "x", 
     "y" 
    ) 

    def __init__(self, obj, x, y): 
     super().__init__(obj, x=x, y=y) 

qui permet maintenant la manipulation:

>>> b = Bar(x=3, y=4) 
>>> b.x 
3 
>>> # Etc. 

J'essaie de garder cela aussi sec que possible parce que je dois sous-classe _Base beaucoup .

+1

Vous ne le définissez pas sur la classe, vous le définissez sur l'objet. Les descripteurs ne fonctionnent pas comme ça. –

Répondre

2

property Les objets sont descriptors et les descripteurs sont uniquement invoqués lorsqu'ils sont définis sur la classe ou la métaclasse. Vous ne pouvez pas les mettre directement sur une instance; l'implémentation __getattribute__ pour les classes n'invoque tout simplement pas le comportement de liaison requis.

Vous devez mettre la propriété sur la classe, et non pas sur chaque instance:

class Foo: 
    def __init__(self, x): 
     self._x = x 

    @property 
    def x(self): return self._x 

    @x.setter 
    def x(self, y): self._x = y 

Si vous devez avoir une propriété qui ne fonctionne que sur certains cas, vous devrez modifier votre getter et setter des méthodes pour faire varier le comportement (comme augmenter un AttributeError lorsque l'état de l'instance est tel que l'attribut "n'existe pas").

class Bar: 
    def __init__(self, has_x_attribute=False): 
     self._has_x_attribute = has_x_attribute 
     self._x = None 

    @property 
    def x(self): 
     if not self._has_x_attribute: 
      raise AttributeError('x') 
     return self._x 

    @x.setter 
    def x(self, y): 
     if not self._has_x_attribute: 
      raise AttributeError('x') 
     self._x = y 

L'objet property existe encore et est lié, mais se comporte comme si l'attribut n'existe pas lorsqu'un drapeau est défini sur false.

+0

Je viens de réaliser à quel point ma tentative était stupide. Merci. –