[python] __getattr__과 __getattribute__의 차이점
__getattr__
또는 사용시기를 이해하려고합니다 __getattribute__
. 언급 된 문서 는 __getattribute__
새로운 스타일의 클래스에 적용됩니다. 새로운 스타일의 수업은 무엇입니까?
답변
사이의 키 차이 __getattr__
와는 __getattribute__
즉 __getattr__
속성이 일반적인 방법을 찾을 수 없습니다 경우에만 호출됩니다. 누락 된 속성에 대한 폴백을 구현하는 데 유용하며 원하는 두 가지 중 하나 일 수 있습니다.
__getattribute__
객체의 실제 속성을보기 전에 호출되므로 올바르게 구현하기가 까다로울 수 있습니다. 무한 재귀로 매우 쉽게 끝날 수 있습니다.
새로운 스타일 클래스는 object
, 구식 클래스에서 파생되며 명시 적 기본 클래스가없는 Python 2.x의 클래스입니다. 그러나 이전 스타일과 새로운 스타일의 클래스의 차이는 사이의 선택 중요한 것이 아니다 __getattr__
및 __getattribute__
.
당신은 거의 확실하게 원합니다 __getattr__
.
답변
마술 방법 __getattr__
과 __getattribute__
마술 방법 의 간단한 예를 살펴 보겠습니다 .
__getattr__
파이썬은 __getattr__
아직 정의되지 않은 속성을 요청할 때마다 메소드 를 호출 합니다. 다음 예제에서 내 클래스 Count 에는 __getattr__
메소드 가 없습니다 . 이제 주에서 나는 액세스하려고 모두 때 obj1.mymin
와 obj1.mymax
모든 것이 잘 작동 속성. 그러나 obj1.mycurrent
속성 에 액세스하려고하면 Python이AttributeError: 'Count' object has no attribute 'mycurrent'
class Count():
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent) --> AttributeError: 'Count' object has no attribute 'mycurrent'
이제 내 클래스 Count 에는 __getattr__
메소드가 있습니다. 이제 obj1.mycurrent
속성 에 액세스하려고하면 파이썬은 내 __getattr__
메소드 에서 구현 한 모든 것을 반환합니다 . 내 예제에서 존재하지 않는 속성을 호출하려고 할 때마다 파이썬은 해당 속성을 만들고 정수 값 0으로 설정합니다.
class Count:
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
def __getattr__(self, item):
self.__dict__[item]=0
return 0
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent1)
__getattribute__
이제 __getattribute__
방법을 봅시다. __getattribute__
클래스에 메소드가있는 경우 python은 존재 여부에 관계없이 모든 속성에 대해이 메소드를 호출합니다. 왜 우리는 __getattribute__
방법이 필요 합니까? 한 가지 좋은 이유는 다음 예제와 같이 속성에 대한 액세스를 방지하고보다 안전하게 만들 수 있기 때문입니다.
누군가가 하위 문자열 ‘cur’로 시작하는 내 속성에 액세스하려고 할 때마다 AttributeError
예외 가 발생합니다. 그렇지 않으면 해당 속성을 반환합니다.
class Count:
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
self.current=None
def __getattribute__(self, item):
if item.startswith('cur'):
raise AttributeError
return object.__getattribute__(self,item)
# or you can use ---return super().__getattribute__(item)
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)
중요 : __getattribute__
메소드 에서 무한 재귀를 피하려면 구현시 항상 동일한 이름을 가진 기본 클래스 메소드를 호출하여 필요한 속성에 액세스해야합니다. : 예를 들어, object.__getattribute__(self, name)
또는 super().__getattribute__(item)
하지self.__dict__[item]
중대한
클래스에 getattr 및 getattribute 매직 메소드 가 모두 포함 된 경우 __getattribute__
먼저 호출됩니다. 그러나 예외 __getattribute__
가
AttributeError
발생하면 예외가 무시되고 __getattr__
메소드가 호출됩니다. 다음 예를 참조하십시오.
class Count(object):
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
self.current=None
def __getattr__(self, item):
self.__dict__[item]=0
return 0
def __getattribute__(self, item):
if item.startswith('cur'):
raise AttributeError
return object.__getattribute__(self,item)
# or you can use ---return super().__getattribute__(item)
# note this class subclass object
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)
답변
이것은 Ned Batchelder의 설명을 기반으로 한 예일뿐입니다 .
__getattr__
예:
class Foo(object):
def __getattr__(self, attr):
print "looking up", attr
value = 42
self.__dict__[attr] = value
return value
f = Foo()
print f.x
#output >>> looking up x 42
f.x = 3
print f.x
#output >>> 3
print ('__getattr__ sets a default value if undefeined OR __getattr__ to define how to handle attributes that are not found')
그리고 같은 예제를 사용 __getattribute__
하면 >>>RuntimeError: maximum recursion depth exceeded while calling a Python object
답변
새 스타일 클래스는 object
또는 다른 새 스타일 클래스에서 상속합니다 .
class SomeObject(object):
pass
class SubObject(SomeObject):
pass
구식 수업은하지 않습니다 :
class SomeObject:
pass
이것은 파이썬 2에만 적용됩니다-파이썬 3에서는 위의 모든 것이 새로운 스타일의 클래스를 만듭니다.
참조 9. 클래스 (파이썬 자습서를) NewClassVsClassicClass 및 파이썬 오래 된 스타일과 새로운 스타일 클래스의 차이점은 무엇입니까? 자세한 내용은.
답변
새로운 스타일 클래스는 “직접”또는 “직접”서브 클래스 인 클래스입니다. 그들은 __new__
수업 방법 __init__
이 있으며 다소 합리적인 수준의 저수준 행동을합니다.
일반적으로 재정의하고 싶을 __getattr__
경우 (중재하는 경우) 메서드 내에서 “self.foo”구문을 지원하는 데 어려움이 있습니다.
추가 정보 : http://www.devx.com/opensource/Article/31482/0/page/4
답변
Beazley & Jones PCB를 통해 읽을 __getattr__
때 OP 질문의 “언제”부분에 대한 답변 을 제공하는 명시적이고 실용적인 사용 사례를 발견했습니다 . 책에서 :
“이 __getattr__()
방법은 일종의 속성 조회와 비슷합니다. 코드가 존재하지 않는 속성에 액세스하려고하면 호출되는 방법입니다.” 우리는 위의 답변에서 이것을 알고 있지만 PCB 레시피 8.15 에서이 기능은 위임 디자인 패턴 을 구현하는 데 사용됩니다 . 오브젝트 A에 오브젝트 B의 메소드를 호출하기 위해 오브젝트 A의 모든 오브젝트 B 메소드를 재정의하는 대신 오브젝트 A가 위임하려는 많은 메소드를 구현하는 오브젝트 B 속성이있는 경우 __getattr__()
다음과 같이 메소드를 정의하십시오 .
def __getattr__(self, name):
return getattr(self._b, name)
여기서 _b는 오브젝트 B 인 오브젝트 A의 속성 이름입니다. 오브젝트 B에 정의 된 __getattr__
메소드가 오브젝트 A에서 호출 되면 메소드는 검색 체인의 끝에서 호출됩니다. 다른 객체에 위임하기 위해 정의 된 메소드 목록이 없기 때문에 코드도 깔끔해집니다.