2009-05-02 7 views
2

의 우리가 클래스와 그 방법을 포장, 새로운 클래스의 몸을 산책 메타 클래스 CallableWrappingMeta, InstanceMethodWrapper있어 가정 해 봅시다 :. 그들이에서 와서instancemethod로 호출 할 수 있습니까?

import types 

class CallableWrappingMeta(type): 
    def __new__(mcls, name, bases, cls_dict): 
     for k, v in cls_dict.iteritems(): 
      if isinstance(v, types.FunctionType): 
       cls_dict[k] = InstanceMethodWrapper(v) 
     return type.__new__(mcls, name, bases, cls_dict) 

class InstanceMethodWrapper(object): 
    def __init__(self, method): 
     self.method = method 
    def __call__(self, *args, **kw): 
     print "InstanceMethodWrapper.__call__(%s, *%r, **%r)" % (self, args, kw) 
     return self.method(*args, **kw) 

class Bar(object): 
    __metaclass__ = CallableWrappingMeta 
    def __init__(self): 
     print 'bar!' 

우리의 더미 래퍼 그냥 인수를 인쇄를하지만 눈에 띄는 것이 있습니다 :이 메서드는 인스턴스 객체 수신기를 통과하지 못합니다. 왜냐하면 InstanceMethodWrapper이 호출 가능하기는하지만 클래스 작성 중에 인스턴스 메소드로 변환 될 목적으로 함수로 처리되지 않기 때문입니다 (메타 클래스가 그것으로 끝났다).

해결 방법 가능한 해결책은 클래스 대신 데코레이터를 사용하여 메서드를 래핑하는 것입니다.이 메서드는 인스턴스 메서드가됩니다. 그러나 현실 세계에서는 InstanceMethodWrapper이 훨씬 더 복잡합니다. API를 제공하고 메소드 호출 이벤트를 게시합니다. 수업이 더 편리합니다. (더 많은 성과를 거두지 않아도됩니다.)

나는 또한 막 다른 골목을 시도했다. 서브 클래스 types.MethodTypetypes.UnboundMethodType은 어디에도 없었습니다. 조금 내성적이며, 그들은 type에서 탈퇴 한 것으로 보입니다. 그래서 저는이 두 가지를 모두 메타 클래스로 사용하려했지만 거기에서도 운이 없었습니다. 그들이 메타 클래스로서 특별한 요구를하는 경우일지도 모르지만,이 시점에서 우리는 문서화되지 않은 영역에있는 것 같습니다.

아이디어가 있으십니까?

+0

더 자세히 설명해 주시겠습니까? 나는 너가하고있는 것을 이해하는 데 어려움을 겪고있다. – Unknown

답변

3

그냥 (완벽하게 잘 단지 return self 수있는)를 __get__ 당신에게 InstanceMethodWrapper 클래스를 풍성하게. 배경 및 세부 정보는 http://users.rcn.com/python/download/Descriptor.htm을 참조하십시오.

사실 필자가 Python 2.6 이상을 사용하는 경우 해당 메타 클래스 대신 클래스 데코레이터를 사용하는 것이 좋습니다. 이렇게 많은 메타 클래스가 장식 용도로만 사용 되었기 때문에 클래스 장식자를 정확하게 추가했으며 데코레이터는 실제로 훨씬 더 간단하게 사용할 수 있습니다.

0

편집 : 나는 다시 거짓말을합니다. 함수에 대한 __?attr__ 속성은 읽기 전용이지만 할당 할 때 항상 AttributeException 예외를 throw하지는 않습니까? 나는 몰라. 원점으로 돌아가다!

편집 : 랩핑 기능이 InstanceMethodWrapper에 대한 속성 요청을 프록시 지정하지 않기 때문에 실제로 문제가 해결되지 않습니다. 물론 장식 자에 __?attr__ 속성을 넣을 수 있습니다. 그리고 지금 제가하고있는 일입니다.하지만 그것은 추한 것입니다. 더 나은 아이디어는 대단히 환영합니다.

def methodize(method, callable): 
    "Circumvents the fact that callables are not converted to instance methods." 
    @wraps(method) 
    def wrapper(*args, **kw): 
     return wrapper._callable(*args, **kw) 
    wrapper._callable = callable 
    return wrapper 

그런 다음 메타 클래스에 InstanceMethodWrapper로 통화에 장식을 추가합니다 :

물론


, 내가 바로 우리의 클래스와 간단한 장식을 결합하는 트릭을 할 것입니다 것을 깨달았다

cls_dict[k] = methodize(v, InstanceMethodWrapper(v)) 

포프. 약간 비스듬하지만 작동합니다.

0

사용자 정의 함수를 사용하여 클래스의 모든 메소드를 래핑하는 메타 클래스를 만들려고합니다.

여기 내 생각에는 조금 덜 기울어졌습니다.

import types 

class CallableWrappingMeta(type): 
    def __new__(mcls, name, bases, cls_dict): 
     instance = type.__new__(mcls, name, bases, cls_dict) 
     for k in dir(instance): 
      v = getattr(instance, k) 
      if isinstance(v, types.MethodType): 
       setattr(instance, k, instanceMethodWrapper(v)) 

     return instance 

def instanceMethodWrapper(function): 
    def customfunc(*args, **kw): 
     print "instanceMethodWrapper(*%r, **%r)" % (args, kw) 
     return function(*args, **kw) 
    return customfunc 

class Bar(object): 
    __metaclass__ = CallableWrappingMeta 

    def method(self, a, b): 
     print a,b 

a = Bar() 
a.method("foo","bar") 
0

나는 당신이 당신의 문제에 대해 더 구체적으로 생각할 필요가 있다고 생각합니다. 원래의 질문은 함수를 래핑하는 것에 대해 이야기하지만, 후속 해답은 함수 속성을 보존하는 것에 대해 말하는 것처럼 보입니다. 이는 새로운 요소 인 것 같습니다. 설계 목표를보다 명확하게 설명하면 질문에 쉽게 답할 수 있습니다.그 인스턴스가 기술자 객체가되도록 즉,하는 설명 형으로 클래스를 만들 -

관련 문제