Python 속성은 어떻게 작동합니까?


78

Python 속성을 성공적으로 사용했지만 어떻게 작동하는지 모르겠습니다. 클래스 외부의 속성을 역 참조하면 property다음 유형의 객체를 얻습니다 .

@property
def hello(): return "Hello, world!"

hello  # <property object at 0x9870a8>

그러나 클래스에 속성을 넣으면 동작이 매우 다릅니다.

class Foo(object):
   @property
   def hello(self): return "Hello, world!"

Foo().hello # 'Hello, world!'

언 바운드 Foo.hello가 여전히 property객체 라는 것을 알았 으므로 클래스 인스턴스화가 마법을 수행해야하지만 그 마법은 무엇입니까?



@MartinThoma, 감사합니다!
Kushan Gunasekera

3
@MartinThoma max recursion depth exceeded... hahaa
자인 아르 샤드

답변:


54

다른 사람들이 언급했듯이 설명 자라는 언어 기능을 사용합니다.

클래스를 통해 액세스 할 때 실제 속성 개체가 반환되는 이유 Foo.hello는 속성이 __get__(self, instance, owner)특수 메서드를 구현하는 방법에 있습니다.

  • 설명자가 인스턴스 에서 액세스되면 해당 인스턴스가 적절한 인수로 전달되고 해당 인스턴스 owner클래스 입니다.
  • 클래스를 통해 액세스하면 instanceNone이고 만 owner전달됩니다. property객체는이 반환을 인식합니다 self.

Descriptors howto 외에도 Language Guide의 Implementing DescriptorsInvoking Descriptors 문서를 참조하세요 .


25

@properties가 제대로 작동하려면 클래스가 object 의 하위 클래스 여야 합니다 . 클래스가 객체 의 하위 클래스가 아닌 경우 처음으로 setter에 액세스하려고하면 실제로는 setter를 통해 액세스하는 대신 더 짧은 이름을 가진 새 속성을 만듭니다.

다음은 올바르게 작동 하지 않습니다 .

class C(): # <-- Notice that object is missing

    def __init__(self):
        self._x = None

    @property
    def x(self):
        print 'getting value of x'
        return self._x

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

>>> c = C()
>>> c.x = 1
>>> print c.x, c._x
1 0

다음은 올바르게 작동합니다.

class C(object):

    def __init__(self):
        self._x = None

    @property
    def x(self):
        print 'getting value of x'
        return self._x

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

>>> c = C()
>>> c.x = 1
setting value of x
>>> print c.x, c._x
getting value of x
1 1

31
Python 3부터는 객체 로부터의 상속 이 더 이상 필요하지 않습니다.
DeFazer

8
또는 더 정확하게는 Python 3에서 클래스는 는 기본적으로 객체 하므로 코드에 명시 적으로 작성할 필요가 없습니다.
Nathaniel Verhaaren

12

속성은 설명자 이며 설명자는 클래스 인스턴스의 구성원 일 때 특별히 작동합니다. 간단히 말해a 타입의 인스턴스 AA.foo디스크립터는 다음이다 a.foo동등하다 A.foo.__get__(a).


사실, 그들은 또한 (Python 2.7에서) 구식 클래스로 작동하는 것 같습니다. 그러나 링크 주셔서 감사합니다.
Fred Foo

에 대한 메서드 서명 __get__()이 잘못되었습니다. self 외에 두 개의 인수가 있습니다. 그렇지 않으면 잘 설명되었습니다.
Tim Yates

@larsmans : 링크 된 페이지에서 : "설명자는 새 스타일 객체 또는 클래스에 대해서만 호출됩니다." 예전 스타일 수업에 시도해 본 것도 기억합니다.
Sven Marnach

@Tim : 두 번째 인수는 선택 사항입니다.
Sven Marnach

2
@larsmans : 몇 가지 간단한 테스트를했습니다. 설명자 자체의 유형은 새로운 스타일의 클래스 여야합니다. 그렇지 않으면 작동하지 않습니다. 설명자를 포함하는 클래스는 중요하지 않습니다. 위의 인용문은 어느 쪽이든 읽을 수 있습니다.
Sven Marnach

2

property목적은 단지 설명 프로토콜을 구현 : http://docs.python.org/howto/descriptor.html


15
나는이 경우 dw 뒤에있는 추론을 확실히 이해합니다.이 답변과 수락 된 답변 모두 실제 설명 이 없으며 기본적으로 링크입니다. 일부 오류 해결 사례에서는 이것이 충분하지만 OP는 주제에 대한 인간의 설명을 찾고있는 것 같습니다.
Morgan Wilde
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.