__getattr__과 __getattribute__의 차이점 이해
나는 사이의 차이를 이해하려고 __getattr__
하고 __getattribute__
, 그러나, 나는 그것을 실패하고있다.
대답 스택 오버플로 질문에 차이 __getattr__
대는__getattribute__
말합니다 :
__getattribute__
객체의 실제 속성을보기 전에 호출되므로 올바르게 구현하기가 까다로울 수 있습니다. 무한 재귀로 매우 쉽게 끝날 수 있습니다.
나는 그것이 무엇을 의미하는지 전혀 모른다.
그런 다음 계속 말합니다.
당신은 거의 확실하게 원합니다
__getattr__
.
왜?
나는 경우 읽었 __getattribute__
실패 __getattr__
라고합니다. 그렇다면 왜 같은 일을하는 두 가지 방법이 있습니까? 내 코드가 새로운 스타일 클래스를 구현하는 경우 무엇을 사용해야합니까?
이 질문을 해결하기 위해 몇 가지 코드 예제를 찾고 있습니다. Google은 최선을 다해 최선을 다했지만 찾은 답변으로 문제에 대해 자세히 논의하지는 않습니다.
문서가 있으면 읽을 준비가되었습니다.
몇 가지 기본 사항.
객체를 사용하면 해당 속성을 처리해야합니다. 보통 우리는 그렇습니다 instance.attribute
. 때로는 더 많은 제어가 필요합니다 (사전 속성의 이름을 모르는 경우).
예를 들어, instance.attribute
될 것입니다 getattr(instance, attribute_name)
. 이 모델을 사용하면 attribute_name 을 문자열로 제공하여 속성 을 얻을 수 있습니다 .
사용 __getattr__
또한 클래스를 통해 명시 적으로 관리하지 않는 속성을 처리하는 방법을 __getattr__
메소드 를 통해 지정할 수 있습니다 .
파이썬은 아직 정의되지 않은 속성을 요청할 때마다이 메소드를 호출하므로 그와 관련된 작업을 정의 할 수 있습니다.
전형적인 사용 사례 :
class A(dict):
def __getattr__(self, name):
return self[name]
a = A()
# Now a.somekey will give a['somekey']
주의 사항 및 사용 __getattribute__
당신은 모든 속성을 잡을해야하는 경우 에 관계없이 존재 여부 , 사용 __getattribute__
대신. 차이점은 __getattr__
실제로 존재하지 않는 속성 만 호출한다는 것입니다. 속성을 직접 설정 한 경우 해당 속성을 참조하면을 호출하지 않고 속성을 검색합니다 __getattr__
.
__getattribute__
항상 호출됩니다.
__getattribute__
속성 액세스가 발생할 때마다 호출됩니다.
class Foo(object):
def __init__(self, a):
self.a = 1
def __getattribute__(self, attr):
try:
return self.__dict__[attr]
except KeyError:
return 'default'
f = Foo(1)
f.a
이로 인해 무한 재귀가 발생합니다. 여기서 범인은 선 return self.__dict__[attr]
입니다. 모든 속성이 self.__dict__
이름으로 저장 되고 사용 가능한 것으로 가장합니다 (진실에 가깝습니다) . 라인
f.a
의 a
속성에 액세스하려고합니다 f
. 이 호출합니다 f.__getattribute__('a')
. __getattribute__
그런 다음로드를 시도합니다 self.__dict__
. __dict__
의 속성 self == f
이므로 파이썬 호출 은 속성에 f.__getattribute__('__dict__')
다시 액세스하려고합니다 '__dict__
. 이것은 무한 재귀입니다.
__getattr__
대신에 사용 되었다면
- 속성
f
이 있기 때문에 실행되지 않았을 것a
입니다. - 그것이 실행 되었다면 (당신이 요청했다고 가정 해 봅시다
f.b
)__dict__
이미 거기에 있기 때문에 찾기 위해 호출되지 않았을 것이고 속성을 찾는 다른 모든 방법이 실패__getattr__
했을 때만 호출됩니다 .
위의 클래스를 사용하여 '올바른'방법 __getattribute__
은
class Foo(object):
# Same __init__
def __getattribute__(self, attr):
return super(Foo, self).__getattribute__(attr)
super(Foo, self).__getattribute__(attr)
binds the __getattribute__
method of the 'nearest' superclass (formally, the next class in the class's Method Resolution Order, or MRO) to the current object self
and then calls it and lets that do the work.
All of this trouble is avoided by using __getattr__
which lets Python do it's normal thing until an attribute isn't found. At that point, Python hands control over to your __getattr__
method and lets it come up with something.
It's also worth noting that you can run into infinite recursion with __getattr__
.
class Foo(object):
def __getattr__(self, attr):
return self.attr
I'll leave that one as an exercise.
I think the other answers have done a great job of explaining the difference between __getattr__
and __getattribute__
, but one thing that might not be clear is why you would want to use __getattribute__
. The cool thing about __getattribute__
is that it essentially allows you to overload the dot when accessing a class. This allows you to customize how attributes are accessed at a low level. For instance, suppose I want to define a class where all methods that only take a self argument are treated as properties:
# prop.py
import inspect
class PropClass(object):
def __getattribute__(self, attr):
val = super(PropClass, self).__getattribute__(attr)
if callable(val):
argcount = len(inspect.getargspec(val).args)
# Account for self
if argcount == 1:
return val()
else:
return val
else:
return val
And from the interactive interpreter:
>>> import prop
>>> class A(prop.PropClass):
... def f(self):
... return 1
...
>>> a = A()
>>> a.f
1
Of course this is a silly example and you probably wouldn't ever want to do this, but it shows you the power you can get from overriding __getattribute__
.
'IT' 카테고리의 다른 글
대상이 최신이라고 생각하는 이유는 무엇입니까? (0) | 2020.05.13 |
---|---|
mysql에서“잘못된 조합의 데이터 정렬”오류 문제 해결 (0) | 2020.05.13 |
IP 주소에서 위치 얻기 (0) | 2020.05.13 |
PHP를 사용하여 클라이언트 IP 주소 얻기 (0) | 2020.05.13 |
GitHub README.md에 비디오를 포함시키는 방법은 무엇입니까? (0) | 2020.05.13 |