문제

다음과 같은 원리를 가진 데코레이터로 사용하기위한 클래스를 구성하고 싶습니다.

  1. 이러한 클래스 데코레이터를 상단 1 기능에 쌓을 수 있어야합니다.
  2. 결과 함수 이름 포인터는 데코레이터없이 동일한 함수와 구별 할 수 없어야합니다. 어떤 유형/클래스인지 저장할 수 있습니다.
  3. 데코레이터를 주문하는 것은 실제로 데코레이터가 의무화하지 않는 한 관련이 없어야합니다. 즉. 독립적 인 데코레이터는 어떤 순서로든 적용 할 수 있습니다.

이것은 Django 프로젝트를위한 것이며, 지금 작업중인 특정 사례에는 2 개의 데코레이터가 필요하며 일반적인 파이썬 기능으로 나타납니다.

@AccessCheck
@AutoTemplate
def view(request, item_id) {}

@autoTemplate은 httpresponse를 반환하는 대신 컨텍스트에서 사용하기 위해 사전을 반환하도록 함수를 변경합니다. RequestContext가 사용되며 템플릿 이름은 메소드 이름과 모듈에서 추론됩니다.

@AccessCheck은 item_id를 기반으로 사용자에게 추가 점검을 추가합니다.

생성자를 제대로 얻고 적절한 속성을 복사하는 것이 단지 어떤 속성입니까?

다음과 같은 데코레이터는 다음과 같이 작동하지 않습니다.

class NullDecl (object):
    def __init__ (self, func):
        self.func = func
    def __call__ (self, * args):
        return self.func (*args)

다음 코드에서 설명한대로 :

@NullDecl
@NullDecl
def decorated():
    pass

def pure():
    pass

# results in set(['func_closure', 'func_dict', '__get__', 'func_name',
# 'func_defaults', '__name__', 'func_code', 'func_doc', 'func_globals'])
print set(dir(pure)) - set(dir(decorated));

또한 "인쇄 기능을 추가하십시오.이름"Nulldecl 생성자에서는 첫 번째 데코레이터에서 작동하지만 두 번째는 그렇지 않습니다. 이름이 누락 될 것입니다.

세련된 Eduffy대답은 조금 잘 작동하는 것 같습니다.

class NullDecl (object):
    def __init__ (self, func):
        self.func = func
        for n in set(dir(func)) - set(dir(self)):
            setattr(self, n, getattr(func, n))

    def __call__ (self, * args):
        return self.func (*args)
    def __repr__(self):
        return self.func
도움이 되었습니까?

해결책

아무것도없는 데코레이터 클래스는 다음과 같습니다.

class NullDecl (object):
   def __init__ (self, func):
      self.func = func
      for name in set(dir(func)) - set(dir(self)):
        setattr(self, name, getattr(func, name))

   def __call__ (self, *args):
      return self.func (*args)

그런 다음 정상적으로 적용 할 수 있습니다.

@NullDecl
def myFunc (x,y,z):
   return (x+y)/z

다른 팁

그만큼 데코레이터 모듈 시그니처 보존 데코레이터를 작성하는 데 도움이됩니다.

그리고 Pythondecoratorlibrary 데코레이터에게 유용한 예를 제공 할 수 있습니다.

원래 함수와 구별 할 수없는 문제에서 기능을 감싸는 데코레이터를 만들려면 사용하십시오. functools.wraps.

예시:


def mydecorator(func):
    @functools.wraps(func):
    def _mydecorator(*args, **kwargs):
        do_something()
        try:
            return func(*args, **kwargs)
        finally:
            clean_up()
    return _mydecorator

# ... and with parameters
def mydecorator(param1, param2):
    def _mydecorator(func):
        @functools.wraps(func)
        def __mydecorator(*args, **kwargs):
            do_something(param1, param2)
            try:
                return func(*args, **kwargs)
            finally:
                clean_up()
        return __mydecorator
    return _mydecorator

(내 개인적인 취향은 클래스가 아닌 기능을 사용하여 데코레이터를 만드는 것입니다)

데코레이터의 순서는 다음과 같습니다.


@d1
@d2
def func():
    pass

# is equivalent to
def func():
    pass

func = d1(d2(func))
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top