IT

왜 파이썬에서 @ foo.setter가 작동하지 않습니까?

lottoking 2020. 6. 8. 08:04
반응형

왜 파이썬에서 @ foo.setter가 작동하지 않습니까?


그래서 파이썬 2.6에서 데코레이터를 가지고 놀고 있는데, 그것들을 작동시키는 데 어려움이 있습니다. 내 수업 파일은 다음과 같습니다.

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에서 이러한 함수를 호출하는 것입니다. 그래서 유휴 상태를 발생시키고 확인했습니다.

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

getter를 호출하기 때문에 첫 번째 호출은 예상대로 작동하며 기본값이 없으며 실패합니다. 알았어요, 이해합니다 그러나 할당 호출 t.x = 5은 새로운 속성을 생성하는 것으로 보이며 x이제 getter가 작동하지 않습니다!

내가 무엇을 놓치고 있습니까?


파이썬 2에서 고전적인 구식 클래스사용하고있는 것 같습니다. 속성 이 제대로 작동하려면 대신 새 스타일 클래스 를 사용해야합니다 (파이썬 2에서는에서 상속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
>>> 

문제를 일으킬 수있는 또 다른 세부 사항은 두 메소드 모두 특성이 작동하려면 동일한 이름이 필요하다는 것입니다. 이와 같은 다른 이름으로 setter를 정의하면 작동하지 않습니다 .

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

그리고 처음에는 완전히 발견하기 쉽지 않은 또 하나의 순서는 순서입니다. 게터를 먼저 정의해야합니다 . 세터를 먼저 정의하면 name 'x' is not defined오류가 발생합니다.


Just a note for other people who stumble here looking for this exception: both functions need to have the same name. Naming the methods as follows will result in an exception:

@property
def x(self): pass

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

Instead give both methods the same name

@property
def x(self): pass

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

It is also important to note that the order of the declaration matters. The getter must be defined before the setter in the file or else you will get a NameError: name 'x' is not defined


You need to use new-style classes which you do by deriving your class from object:

class testDec(object):
   ....

Then it should work.


In case anybody comes here from google, in addition to the above answers I would like to add that this needs careful attention when invoking the setter from the __init__ method of your class based on this answer Specifically:

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

참고URL : https://stackoverflow.com/questions/598077/why-does-foo-setter-in-python-not-work-for-me

반응형