2017-12-17 77 views
4

첫 번째 데모 :__getattr__ 및 __getattribute__에 대한 몇 가지 질문이 있습니까?

class B: 
    def __init__(self): 
     self.name = '234' 
    # def __getattribute__(self, name): 
    #  print('getattr') 
    def __getattr__(self, name):  
     print('get') 
    def __setattr__(self, name, value): 
     print('set') 
    def __delattr__(self, name): 
     print('del') 


b = B() 
print(b.__dict__) 
b.name 

b.__dict__{}이지만, 두 번째 데모 :

class B: 
    def __init__(self): 
     self.name = '234' 
    def __getattribute__(self, name): 
     print('getattr') 
    def __getattr__(self, name): 
     print('get') 
    def __setattr__(self, name, value): 
     print('set') 
    def __delattr__(self, name): 
     print('del') 


b = B() 
print(b.__dict__) 
b.name 

b.__dict__, 왜 None입니까? 그리고 b.__dict____getattribute__을 호출하지만 __getattr__을 호출하지 않습니다. __getattribute____getattr__을 호출하지 못하게합니까?

답변

5

모든 속성 액세스 (가져 오기, 설정 및 삭제)에 대해 __getattribute__, __setattr____delattr__ 메쏘드가 호출됩니다. 반면에 __getattr__은 누락 된 속성에 대해서만 호출되는 입니다.; 일반적으로 아직 구현되어 있지 않지만, __getattribute__은 속성을 찾을 수 없거나 AttributeError__getattribute__에 의해 생성 된 경우 호출합니다.

3 가지 기본 방법의 표준 구현을 인쇄 만하고 None (명시적인 return 문이없는 경우 기본값)을 반환하는 메서드로 바꿨습니다. __dict__은 다른 속성 액세스 일 뿐이므로 __getattribute__ 메서드는 None을 반환하고 절대로 __getattr__을 호출하거나 AttributeError을 발생시키지 않습니다. Customizing attribute access documentation에서

: 속성 조회가 (이 인스턴스 속성되지 않은 즉,도 아니다 self의 클래스 트리에서 발견된다) 일반적인 장소에서 속성을 찾을 수 없습니다 때 호출

object.__getattr__(self, name)
. 속성을 구현하기 위해 무조건 호출

object.__getattribute__(self, name)

클래스의 인스턴스에 액세스합니다. 클래스가 __getattr__()을 정의하는 경우 __getattribute__()이 명시 적으로 호출하거나 AttributeError을 발생시키지 않으면 클래스가 호출되지 않습니다.

(굵게 강조 표시).

은 (super().__getattribute__ 통해)베이스 구현을 호출하거나 AttributeError 상향 어느 : super().__getattribute__ 호출하여 실제 __dict__ 특성이 발견되었는지

>>> class B: 
...  def __init__(self): 
...   self.name = '234' 
...  def __getattribute__(self, name): 
...   print('getattr') 
...   return super().__getattribute__(name) 
...  def __getattr__(self, name): 
...   print('get') 
...  def __setattr__(self, name, value): 
...   print('set') 
...  def __delattr__(self, name): 
...   print('del') 
... 
>>> b = B() 
set 
>>> b.__dict__ 
getattr 
{} 
>>> b.name 
getattr 
get 
>>> class B: 
...  def __init__(self): 
...   self.name = '234' 
...  def __getattribute__(self, name): 
...   print('getattr') 
...   raise AttributeError(name) 
...  def __getattr__(self, name): 
...   print('get') 
...  def __setattr__(self, name, value): 
...   print('set') 
...  def __delattr__(self, name): 
...   print('del') 
... 
>>> b = B() 
set 
>>> b.__dict__ 
getattr 
get 
>>> b.name 
getattr 
get 

참고. AttributeError을 대신 호출하면 __getattr__이 호출되어 None을 반환했습니다.

+0

'b.name'도'__getattr__'을 호출하지 않지만'b'는 속성'name'을 가지고 있지 않으므로'__getattr__'을 호출하지 마십시오. – gaussclb

+0

@gaussclb :'b.name' ** **'__getattribute__'를 호출합니다; 'get'이 인쇄됩니다. –

+0

'getattr'을'get'하지 않고 출력합니다,'__getattr__'을 호출하지 않으시겠습니까? – gaussclb