@property의 용도는 무엇인가요? 표면적으로는 메소드에 속성으로 액세스하는 것입니다.
코드가 가장 명확합니다
class Circle(object): def __init__(self, radius): self.radius = radius @property def area(self): return 3.14 * self.radius ** 2 c = Circle(4) print c.radius print c.area
area는 메소드로 정의되어 있지만 @property를 추가하면 c.area를 직접 프로퍼티로 접근할 수 있는 것을 볼 수 있습니다.
이제 질문이 옵니다. 시간 c.area가 호출되면 한 번 계산되는데 CPU를 어떻게 한 번만 계산할 수 있습니까? 이것은 게으른 속성입니다.
class lazy(object): def __init__(self, func): self.func = func def __get__(self, instance, cls): val = self.func(instance) setattr(instance, self.func.__name__, val) return val class Circle(object): def __init__(self, radius): self.radius = radius @lazy def area(self): print 'evalute' return 3.14 * self.radius ** 2 c = Circle(4) print c.radius print c.area print c.area print c.area
보시다시피 'evalute'는 한 번만 출력됩니다. 이전 블로그 게시물을 읽으셨다면 @lazy의 메커니즘을 잘 이해하셔야 합니다.
여기서, 게으른 클래스에는 이를 나타내는 __get__ 메소드가 있습니다. c.area가 처음 실행될 때 순서 문제 때문에 먼저 c.__dict__에서 검색합니다. 찾지 못하면 클래스 공간으로 이동하여 검색합니다. 은area() 메소드이므로 __get__에 의해 가로채어집니다.
__get__에서는 인스턴스의area() 메소드를 호출하여 결과를 계산하고 인스턴스에 동적으로 동일한 이름의 속성을 추가하고 할당합니다. 즉, c.__dict__에 추가합니다.
c를 다시 .area로 실행하고, 먼저 c.__dict__로 이동하여 찾으세요. 현재 이미 존재하기 때문에 해당 영역을 거치지 않습니다( ) 메소드 및 __get__.
참고
다음 코드 시나리오에 주의하세요.
코드 조각 1:
Python2.6 코드
class Parrot(object): def __init__(self): self._voltage = 100000 @property def voltage(self): """Get the current voltage.""" return self._voltage if __name__ == "__main__": # instance p = Parrot() # similarly invoke "getter" via @property print p.voltage # update, similarly invoke "setter" p.voltage = 12
코드 조각 2:
Python2.6 코드
class Parrot: def __init__(self): self._voltage = 100000 @property def voltage(self): """Get the current voltage.""" return self._voltage if __name__ == "__main__": # instance p = Parrot() # similarly invoke "getter" via @property print p.voltage # update, similarly invoke "setter" p.voltage = 12
코드 1과 2의 차이점은
class Parrot(object):
python2.6에서
조각 테스트를 각각 실행합니다. 1: 예상되는 오류 메시지가 표시됩니다. AttributeError: 속성을 설정할 수 없습니다.
조각 2: 올바르게 실행
python2.6 문서를 참조하세요. @property는 읽기 전용 속성을 제공하지만 위 코드는 해당 @volt.setter를 제공하지 않습니다. 이는 스니펫 2 코드가 실행 오류를 표시하는 이유입니다. python2.6 문서에서 다음 정보를 찾을 수 있습니다.
BIF:
property([fget[, fset[ , fdel[, doc]]]])
속성 속성 반환 새로운 스타일의 클래스(객체에서 파생된 클래스)의 경우
python2.6에서는 클래스 정의 시 명확한 설명이 없으면 내장형 객체가 기본 기본 클래스가 아닌 것으로 나타났습니다(코드). 코드 조각 2), 우리가 정의한 Parrot(코드 조각 2)은 객체
를 상속하지 않으며 객체 클래스는 우리에게 필요한 @property 함수만 제공합니다.
새 스타일 클래스
객체에서 상속되는 모든 클래스입니다. 여기에는 목록 및 사전과 같은 모든 내장 유형이 포함됩니다. 새 스타일 클래스만 __slots__, 설명자, 속성 및 __getattribute__(와 같은 Python의 최신 다목적 기능을 사용할 수 있습니다. ).
동시에 다음 방법을 통해서도 확인할 수 있습니다.
Python 2.6 코드
class A: pass >>type(A) <type 'classobj'>
Python 2.6 코드
class A(object): pass >>type(A) <type 'type'>
반환된
Python 버전의 코드를 고려하기 위해 호환성에 관해 전환 기간 동안 문제가 발생하므로 클래스 파일을 정의할 때 객체를 좋은 습관으로 명시적으로 정의해야 한다고 생각합니다.
최종 코드는 다음과 같습니다.
class Parrot(object): def __init__(self): self._voltage = 100000 @property def voltage(self): """Get the current voltage.""" return self._voltage @voltage.setter def voltage(self, new_value): self._voltage = new_value if __name__ == "__main__": # instance p = Parrot() # similarly invoke "getter" via @property print p.voltage # update, similarly invoke "setter" p.voltage = 12
그리고 2.6과 3.0에서는 @property가 추가되었는데 2.5에는 이 기능이 없습니다.
더 많은 Python 흑마법 @property 데코레이터 팁 및 관련 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!