2016-07-10 9 views
1

내가 가지고있는 다음과 같은 클래스 :__getattr__을 사용하여 속성에 메소드를 위임하는 방법은 무엇입니까?

i.__add__(1)TypeError: unsupported operand type(s) for +: 'MyInt' and 'int'를 호출하지 않습니다 :

class MyInt: 
    def __init__(self, v): 
     if type(v) != int: 
      raise ValueError('value must be an int') 
     self.v = v 

    def __getattr__(self, attr): 
     return getattr(self.v, attr) 

i = MyInt(0) 
print(i + 1) 

나는 오류가? 그리고 그러한 메소드가 MyInt 클래스에 없으면 __getattr__을 호출하면 안됩니까?

+2

[정확성을 위해 인스턴스 속성을 우회하는 것 외에도, 암시 적 특수 메소드 조회는 일반적으로 객체의 메타 클래스도 '__getattribute __()'메소드를 무시합니다.] (https://docs.python.org/3/ –

답변

3

__getattr__은 다른 마법 방법을 생성하는 데 사용할 수 없습니다. 모든 항목을 개별적으로 구현해야합니다.

파이썬 언어 내부가 __add__과 같은 마법 메서드를 조회하면 __getattr__, __getattribute__ 및 인스턴스 dict를 완전히 바이 패스합니다. 당신이 정확한 조회 절차를 참조 할 경우 조회는 Objects/typeobject.c에서 _PyObject_LookupSpecial의 대략

def find_magic_method(object, method_name): 
    for klass in type(object).__mro__: 
     if method_name in klass.__dict__: 
      return klass.__dict__[method_name] 
    raise AttributeError 

처럼 간다.

파이썬이 왜 이런 일을하는지 궁금하다면 기대했던 바를 수행하는 것이 정말 어색하거나 불가능할 수있는 많은 마법 방법이 있습니다. 예를 들어, 파이썬에서는 __getattribute__을 사용하여 __getattribute__을 조회 할 수 없기 때문에 기본 케이스없이 무한 재귀가 발생합니다.

+1

실제 조회와 그 파이썬 코드의 차이점은 위의 파이썬 코드는 메타 클래스를 사용하여 사용자 정의'__dict__ '를 제공 할 수 있지만 실제 조회는 메타 클래스를 만들고 기본 C 구조의 직접 필드를 통해'__dict__' 매핑에 액세스합니다. – Bakuriu

+0

긴 파일입니다. 줄 번호 나 함수 이름을 알려주시겠습니까? –

+1

@JonMcClung : 링크가 바로 함수로 간다. 함수 이름이'_PyObject_LookupSpecial '이라고했다. 의존하는 도우미는 대부분 같은 파일에 있으므로 Ctrl-F로 찾을 수 있습니다. – user2357112