2014-02-13 5 views
3

원래 포장 된 함수의 repr() 동작을 유지하는 클래스 기반 데코레이터를 사용하려고했습니다 (functools.wraps 데코레이터가 함수에서 작동하는 방식과 일치시키기 위해). 나는 파이썬 3.3을 사용하고있다.클래스 기반 데코레이터 및 repr() 절약

먼저 나는 functools 시도 :

import functools 

class ClassBasedDecorator(): 
    def __init__(self, fn): 
     self.fn = fn 
     functools.update_wrapper(self, fn) 
    def __call__(self, *args, **kwargs): 
     self.fn(*args, **kwargs) 

@ClassBasedDecorator 
def wrapped(text): 
    pass 

을하지만 장식 기능에 repr()를 호출 할 때, 내가 얻을 :

>>> repr(wrapped) 
'<__main__.ClassBasedDecorator object at 0x2d8860b6850>' 

을 아주 잘, 그래서 난 내 장식의 __repr__ 방법을 사용자 정의하는 시도 이것은 repr()에 의해 호출되어야합니다. 다시

사용 functools :

class ClassBasedDecorator(): 
    def __init__(self, fn): 
     self.fn = fn 
     functools.update_wrapper(
      self, fn, 
      assigned=functools.WRAPPER_ASSIGNMENTS + ('__repr__',) 
     ) 
    def __call__(self, *args, **kwargs): 
     self.fn(*args, **kwargs) 

출력을 변경하지 않습니다,하지만 뭔가 재미있는 일이 :
>>> repr(wrapped) 
'<__main__.ClassBasedDecorator object at 0x2d8860b69d0>' 
>>> wrapped.__repr__() 
'<function wrapped at 0x2d8860a9710>' 

가 명시 적으로 장식 인스턴스의 __repr__ 설정 방법은 같은 효과를가집니다.

조금 더 많은 테스트를 거친 후 repr(instance)은 실제로 instance.__class__.__repr__(instance)을 호출합니다. 따라서 오버라이드 된 __repr__ 인스턴스의 메서드는 호출되지 않습니다.


그래서 여기 내 질문이 있습니다 :

  • repr(instance) 호출 instance.__class__.__repr__(instance) 대신 instance.__repr__()의합니까? 아니면 다른 것을 놓친 적이 있습니까?
  • 장식 된 함수에서 repr() 호출의 결과 변경을 포함하여 클래스 기반의 장식 자에게 함수 기반 데코레이터로 functools.wraps을 수행하는 방법을 완전히 재현 할 수 있습니까?

답변

6

특별한 방법은 인스턴스가 아니라 always looked up on the type of the instance (여기서 클래스 개체)입니다. 그렇지 않으면 클래스의 표현을 인쇄하려고 할 때 클래스의 __repr__이 사용됩니다. type(class).__repr__(class)은 올바른 마법 방법을 사용하지만 이 제공되지 않았기 때문에 class.__repr__()은 예외를 발생시킵니다.

이 구현 자신의 __repr__ 후크 :

class ClassBasedDecorator(): 
    def __init__(self, fn): 
     self.fn = fn 
     functools.update_wrapper(self, fn) 
    def __call__(self, *args, **kwargs): 
     self.fn(*args, **kwargs) 
    def __repr__(self): 
     return repr(self.fn) 

예를 들어, 여전히 __module__, __name____doc__ 속성을 복사하고 함수 __dict__에서 속성을 복사하지만 특별한 방법으로 프록시를 만듭니다.