Pergunta

Então, eu estou jogando com decoradores em Python 2.6, e eu estou tendo alguns problemas começá-los para o trabalho. Aqui está o meu arquivo 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

O que eu pensei que isso significava é x tratar como uma propriedade, mas chamar essas funções em get e set. Então, eu despediu-se IDLE e verificou-lo:

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

É claro que a primeira chamada funciona como esperado, uma vez que eu chamo o getter, e não há nenhum valor padrão, e ele falhar. OK, bem, eu entendo. No entanto, a chamada para t.x = 5 atribuir parece criar um novo x propriedade, e agora o getter não funciona!

O que eu estou ausente?

Foi útil?

Solução

Você parece estar usando aulas clássicas de estilo antigo em python 2. para que propriedades ao trabalho será necessário o uso de classes new-style vez (em python 2 você deve herdar do object ). Apenas declarar sua classe como 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

Ele funciona:

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

Outro detalhe que pode causar problemas é que ambos os métodos precisam do mesmo nome para a propriedade ao trabalho. Se você definir o setter com um nome diferente como este não vai funcionar :

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

E mais uma coisa que não é completamente fácil de detectar no início, é a ordem: O getter deve ser definido pela primeira vez . Se você definir o setter primeiro, receberá o erro name 'x' is not defined.

Outras dicas

Apenas uma nota para outras pessoas que encontraram aqui à procura de uma exceção: as duas funções precisam ter o mesmo nome. Nomear os métodos da seguinte resultará em uma exceção:

@property
def x(self): pass

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

Em vez disso dar a ambos os métodos o mesmo nome

@property
def x(self): pass

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

Também é importante notar que a ordem das matérias de declaração. O getter deve ser definido antes do setter no arquivo, ou então você vai ter um NameError: name 'x' is not defined

Você precisa usar as classes de estilo novo, que você faz por derivar sua classe de objeto:

class testDec(object):
   ....

Em seguida, ele deve funcionar.

Caso alguém vem aqui de google, além das respostas acima, gostaria de acrescentar que este precisa de atenção especial ao chamar o setter do método __init__ de sua classe com base em esta resposta Especificamente:

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top