2009-02-28 4 views
135

그래서 파이썬 2.6에서 데코레이터를 가지고 놀고 있어요. 나는이 의미 무슨 생각을파이썬에서 @ foo.setter가 작동하지 않는 이유는 무엇입니까?

class testDec: 

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

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

는 속성처럼 x을 치료하지만, get 및 set에 이러한 함수를 호출하는 것입니다 : 여기 내 클래스 파일입니다. 그래서, IDLE을 해고하고 확인 : 예상대로 나는 게터를 호출하고 기본값이없고, 실패 이후

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

분명히 첫 번째 호출이 작동합니다. 알았어, 알았어. 그러나 t.x = 5을 할당하는 호출은 새 속성 x을 만드는 것으로 보이며 이제는 getter가 작동하지 않습니다!

무엇이 누락 되었습니까?

class testDec(object): 
    .... 

는 그 다음 작동합니다 :

+6

는 대문자로 클래스의 이름을 지정하십시오. 변수 및 모듈 파일에 소문자를 사용할 수 있습니다. –

답변

258

classic old-style classes을 사용하고있는 것 같습니다. properties이 올바르게 작동하려면 대신 new-style classes (inherit from object)을 사용해야합니다. 그냥 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 

:이 예외를 찾고 여기에 우연히 다른 사람에 대한

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

파이썬 3에서는 더 이상 필요하지 않습니다. "클래식"클래스는 세터와 잘 어울립니다 :-) – Eenoku

+14

모든 클래스가 새로운 스타일의 클래스이기 때문에 파이썬 3에서 작동합니다. 더 이상 '고전적인'클래스는 없습니다. – craigds

22

당신은 당신이 객체에서 클래스를 파생하여 할 새로운 스타일의 클래스를 사용해야합니다.

61

그냥 참고 : 두 함수 모두 같은 이름을 가질 필요가있다. 예외가 발생합니다 다음과 같은 방법을 명명 :

@property 
def x(self): pass 

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

가 대신주의하는 것이 중요하다 같은 이름

@property 
def x(self): pass 

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

에게 두 가지 방법 줄 것을 선언 문제의 순서. getter는 파일의 setter 앞에 정의되어야합니다. 그렇지 않으면 사용자는 NameError: name 'x' is not defined

+0

이것은 아마도 "새로운"최상의 대답이 될 것입니다. 파이썬 3에 점점 더 많은 사람들이 있습니다. – trpt4him

+3

이 답변은 훌륭합니다. 제 생각에이 명령이 중요하다는 것은 말할 수 있다면 완벽 할 것이라고 생각합니다. 즉 getter가 코드에서 setter 앞에 있어야합니다. 그렇지 않으면'NameError : name 'x'not defined '예외가 발생합니다. – eguaio

+0

감사합니다. 나는 이것에 관해 하루의 가장 중요한 부분을 방금 낭비했다. 그 방법이 똑같은 이름으로 불려 져야한다는 것은 결코 내게 발생하지 않았다. 정말 실망스러운 작은 숙어! – ajkavanagh

8

이 될 것입니다. 위의 답변 외에도 누구나 google에서 온다면, 세터를 호출 할 때주의해야합니다. 특히 this answer 에 따라 클래스의 __init__ 방법에서 :

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 
관련 문제