Domanda

Quindi, sto giocando con decoratori in Python 2.6, e sto avendo qualche difficoltà a trovare loro di lavorare. Ecco il mio file di 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

Quello che ho pensato che questo significasse è di trattare x come una proprietà, ma chiamare queste funzioni get e set. Così, ho sparato fino IDLE e controllato:

>>> 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

Chiaramente la prima chiamata funziona come previsto, dal momento che io chiamo il getter, e non v'è alcun valore di default, e viene a mancare. OK, bene, ho capito. Tuttavia, la chiamata per assegnare t.x = 5 sembra creare un nuovo x proprietà, e ora il getter non funziona!

Che cosa mi manca?

È stato utile?

Soluzione

Sembra che tu stia utilizzando classi vecchio stile classico in python 2. al fine di proprietà per funzionare correttamente è necessario utilizzare classi di nuovo stile invece (in python 2 è necessario ereditare da object ). Basta dichiarare la classe come 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

Funziona:

>>> 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 altro dettaglio che potrebbe causare problemi è che entrambi i metodi hanno bisogno lo stesso nome per la proprietà di lavorare. Se si definisce il setter con un nome diverso come questo non funzionerà :

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

E ancora una cosa che non è del tutto facile da individuare in un primo momento, è l'ordine: Il getter deve essere definito prima . Se si definisce il setter prima, si ottiene l'errore name 'x' is not defined.

Altri suggerimenti

Solo una nota per altre persone che inciampano qui in cerca di questa eccezione: entrambe le funzioni devono avere lo stesso nome. Naming metodi come segue si tradurrà in un'eccezione:

@property
def x(self): pass

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

Invece dare entrambi i metodi con lo stesso nome

@property
def x(self): pass

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

E 'anche importante notare che l'ordine degli argomenti di dichiarazione. Il getter deve essere definito prima che il setter nel file, altrimenti si otterrà un NameError: name 'x' is not defined

È necessario utilizzare classi di nuovo stile che si fa derivando la classe da oggetto:

class testDec(object):
   ....

Quindi dovrebbe funzionare.

Nel caso in cui nessuno viene qui da Google, oltre alle risposte di cui sopra vorrei aggiungere che questo ha bisogno di particolare attenzione quando si richiama il setter dal metodo __init__ della classe sulla base di questa risposta In particolare:

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top