2009-04-15 2 views
4

부모 메서드 (꾸미는 클래스의 부모에서 같은 이름의 메서드)를 검사해야하는 메서드의 데코레이터를 작성하고 있습니다. (PEP 318의 제 4 실시 예에서)데코레이터에서 데코 레이팅 된 메서드를 소유하는 클래스에 액세스

예 :

def returns(rtype): 
    def check_returns(f): 
     def new_f(*args, **kwds): 
      result = f(*args, **kwds) 
      assert isinstance(result, rtype), \ 
        "return value %r does not match %s" % (result,rtype) 
      return result 
     new_f.func_name = f.func_name 
     # here I want to reach the class owning the decorated method f, 
     # it should give me the class A 
     return new_f 
    return check_returns 

class A(object): 
    @returns(int) 
    def compute(self, value): 
     return value * 3 

가 그래서 ... 여기 # 내가 원하는 대신에 입력 할 수있는 코드를

감사를 찾고 있어요.

답변

6

bobince said it으로 데코레이터가 호출 될 때 클래스가 아직 존재하지 않기 때문에 주변 클래스에 액세스 할 수 없습니다. 당신은 클래스와 기지의 전체 사전에 액세스해야하는 경우, 당신은 metaclass을 고려해야합니다

__metaclass__

이 변수는 이름, 염기, 및 딕셔너리에 대한 모든 호출 받아들이는 인수 할 수 있습니다. 클래스 생성시 내장 함수() 대신 호출 가능 함수가 사용됩니다. 기본적으로

, 우리는 단지 클래스 건설에 대한 몇 가지 마법을 수행 할 메타 클래스를 알려줍니다 뭔가에 returns 장식을 변환 : 내가해야하는 경우이 코드를 테스트하지 않았습니다

class CheckedReturnType(object): 
    def __init__(self, meth, rtype): 
     self.meth = meth 
     self.rtype = rtype 

def returns(rtype): 
    def _inner(f): 
     return CheckedReturnType(f, rtype) 
    return _inner 

class BaseInspector(type): 
    def __new__(mcs, name, bases, dct): 
     for obj_name, obj in dct.iteritems(): 
      if isinstance(obj, CheckedReturnType): 
       # do your wrapping & checking here, base classes are in bases 
       # reassign to dct 
     return type.__new__(mcs, name, bases, dct) 

class A(object): 
    __metaclass__ = BaseInspector 
    @returns(int) 
    def compute(self, value): 
     return value * 3 

마음을, 의견을 남겨주세요 이것을 업데이트하십시오.

매우 유용한 David Mertz의 답변으로 articles on metaclasses이 있습니다.이 내용은이 맥락에서 흥미로울 수 있습니다.

+0

내 문제는 내가 말한 것보다 훨씬 구체적이기 때문에 코드를 직접 사용하지 않았습니다. 그러나 * name *이 * type * 구조에서 일반적으로 사용되기 때문에 * dct *를 트래버스 할 때 * name *을 사용하는 것이 조금 이상합니다. 고마워, 제게 많은 도움이 되었기 때문에 어쨌든 답을 수락하는 것이 좋습니다. – Gra

+0

아, 그게 실수 야. –

6

여기에서 나는

f를 장식 방법을 소유 클래스에 도달 할 당신 수 없습니다 장식의 시점에서, 어떤 클래스는 방법 F를 소유 없기 때문입니다.

class A(object): 
    @returns(int) 
    def compute(self, value): 
     return value * 3 

는 말과 동일합니다 : 분명히

class A(object): 
    pass 

@returns(int) 
def compute(self, value): 
    return value*3 

A.compute= compute 

, 함수가 소유자 클래스에 할당하기 전에 returns() 장식이 내장되어 있습니다.

이제 함수를 클래스에 (인라인 또는 명시 적으로 이와 같이) 작성하면 바인딩되지 않은 메서드 객체가됩니다. 데코레이터에

>>> A.compute.im_class 
<class '__main__.A'> 

그래서 당신이 할당 후 실행되는 내부 'new_f'를 f.im_class 읽을 수 있지만 : 그것은 당신이 말하는 의해 얻을 수있는 소유자 클래스에 대한 참조가 이제그 자체.

(그렇다고해도 CPython 구현에 대한 의문이 생기지 않는 경우에는 약간의 의문이 생깁니다. 사용자가 무엇을 하려는지 확실하지 않지만 "소유자 클래스 얻기"와 관련된 사항은 다음과 같습니다. 종종 메탈릭을 사용할 수 있습니다.)

관련 문제