Question

Alors, je joue avec des décorateurs en Python 2.6, et je vais avoir un peu de mal à les faire travailler. Voici mon fichier de classe:

class testDec:

    @property
    def x(self): 
        print 'called getter'
        return self._x

    @x.setter
    def x(self, value): 
        print 'called setter'
        self._x = value

Ce que je pensais que cela voulait dire est de traiter x comme une propriété, mais appeler ces fonctions sur get et set. Alors, je pète IDLE et vérifié:

>>> from testDec import testDec
from testDec import testDec
>>> t = testDec()
t = testDec()
>>> t.x
t.x
called getter
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "testDec.py", line 18, in x
    return self._x
AttributeError: testDec instance has no attribute '_x'
>>> t.x = 5
t.x = 5
>>> t.x
t.x
5

Il est clair que le premier appel fonctionne comme prévu, puisque j'appelle le getter, et il n'y a pas de valeur par défaut, et il tombe en panne. OK, bon, je comprends. Cependant, l'appel d'assigner t.x = 5 semble créer une nouvelle x de propriété, et maintenant le getter ne fonctionne pas!

Qu'est-ce que je suis absent?

Était-ce utile?

La solution

Vous semblez être en utilisant les classes classiques de style ancien en python 2. pour propriétés pour fonctionner correctement, vous devez utiliser nouvelles classes de style à la place (en python 2, vous devez hériter de object ). Il suffit de déclarer votre classe comme MyClass(object):

class testDec(object):

    @property
    def x(self): 
        print 'called getter'
        return self._x

    @x.setter
    def x(self, value): 
        print 'called setter'
        self._x = value

Il fonctionne:

>>> k = testDec()
>>> k.x
called getter
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/devel/class_test.py", line 6, in x
    return self._x
AttributeError: 'testDec' object has no attribute '_x'
>>> k.x = 5
called setter
>>> k.x
called getter
5
>>> 

Un autre détail qui pourrait causer des problèmes est que les deux méthodes ont besoin du même nom pour la propriété de travailler. Si vous définissez le setter avec un autre nom comme celui-ci, il ne fonctionnera pas :

@x.setter
def x_setter(self, value):
    ...

Et une chose qui est pas tout à fait facile à repérer dans un premier temps, est l'ordre: Le getter doit être défini en premier . Si vous définissez le poseur d'abord, vous obtenez une erreur name 'x' is not defined.

Autres conseils

Juste une note pour d'autres personnes qui tombent par hasard ici à la recherche de cette exception: les deux fonctions doivent avoir le même nom. Nommer les méthodes comme suit entraînera une exception:

@property
def x(self): pass

@x.setter
def x_setter(self, value): pass

donner lieu les deux méthodes du même nom

@property
def x(self): pass

@x.setter
def x(self, value): pass

Il est également important de noter que l'ordre des questions de déclaration. Le getter doit être définie avant le setter dans le fichier ou bien vous obtiendrez un NameError: name 'x' is not defined

Vous devez utiliser des classes nouveau style que vous faites en dérivant votre classe de l'objet:

class testDec(object):
   ....

Ensuite, il devrait fonctionner.

Dans le cas où tout le monde vient ici de Google, en plus des réponses ci-dessus, je voudrais ajouter que cela a besoin d'une attention particulière lors de l'appel du setter de la méthode de __init__ de votre classe basée sur cette réponse Plus précisément:

class testDec(object):                                                                                                                                            

    def __init__(self, value):
        print 'We are in __init__'
        self.x = value # Will call the setter. Note just x here
        #self._x = value # Will not call the setter

    @property
    def x(self):
        print 'called getter'
        return self._x # Note the _x here

    @x.setter
    def x(self, value): 
        print 'called setter'
        self._x = value # Note the _x here

t = testDec(17)
print t.x 

Output:
We are in __init__
called setter
called getter
17
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top