developer tip

파이썬 클래스 메서드 꾸미기-인스턴스를 데코레이터에 어떻게 전달합니까?

copycodes 2020. 12. 11. 08:24
반응형

파이썬 클래스 메서드 꾸미기-인스턴스를 데코레이터에 어떻게 전달합니까?


이것은 Python 2.5이며 GAE 도 중요하지 않습니다.

다음 코드가 있습니다. dec_check 클래스를 데코레이터로 사용하여 foo () 메서드를 bar로 데코레이션하고 있습니다.

class dec_check(object):

  def __init__(self, f):
    self.func = f

  def __call__(self):
    print 'In dec_check.__init__()'
    self.func()

class bar(object):

  @dec_check
  def foo(self):
    print 'In bar.foo()'

b = bar()
b.foo()

이것을 실행할 때 나는보고 싶었다.

In dec_check.__init__()
In bar.foo()

그러나 나는 " TypeError: foo() takes exactly 1 argument (0 given)"를 얻고 .foo()있다. 객체 메소드이기 때문에 self를 인자로 취한다. 나는 bar데코레이터 코드를 실행할 때 의 인스턴스 가 실제로 존재하지 않는다는 것이 문제라고 생각 합니다.

그렇다면 bar데코레이터 클래스에 의 인스턴스를 어떻게 전달 합니까?


당신은으로 장식을해야 기술자 중 하나는 (메타)을 보장함으로써 클래스는이 - __get__방법, 또는 방법으로 간단을, 데코레이터를 사용하여 기능을 대신 데코레이터 클래스를 (함수가 이미 기술자이기 때문에). 예 :

def dec_check(f):
  def deco(self):
    print 'In deco'
    f(self)
  return deco

class bar(object):
  @dec_check
  def foo(self):
    print 'in bar.foo'

b = bar()
b.foo()

이것은 인쇄

In deco
in bar.foo

바라는대로.


Alex의 대답은 함수가 충분할 때 충분합니다. 그러나 클래스가 필요할 때 데코레이터 클래스에 다음 메서드를 추가하여 작동하도록 만들 수 있습니다.

def __get__(self, obj, objtype):
    """Support instance methods."""
    import functools
    return functools.partial(self.__call__, obj)

이것을 이해하려면 디스크립터 프로토콜을 이해해야합니다. 설명자 프로토콜은 사물을 인스턴스에 바인딩하는 메커니즘입니다. __ get __, __ set __ 및 __ delete __로 구성되며, 인스턴스 사전에서 사물을 가져 오거나 설정하거나 삭제할 때 호출됩니다.

이 경우 인스턴스에서 물건을 가져 왔을 때 부분을 사용하여 __ call __ 메서드의 첫 번째 인수를 인스턴스에 바인딩합니다. 이것은 클래스가 생성 될 때 멤버 함수에 대해 자동으로 수행되지만 이와 같은 합성 멤버 함수의 경우 명시 적으로 수행해야합니다.


데코레이터는 파이썬에서 약간 까다로울 수 있습니다. 언젠가 다시 일하게 된 사례가 있습니다. 당신이하려는 것을 추론 할 수있을 것입니다.

Django 인증 및 Ajax-로그인이 필요한 URL


데코레이터를 클래스로 작성하려면 다음을 수행 할 수 있습니다.

from functools import update_wrapper, partial

class MyDecorator(object):
    def __init__(self, func):
        update_wrapper(self, func)
        self.func = func

    def __get__(self, obj, objtype):
        """Support instance methods."""
        return functools.partial(self.__call__, obj)

    def __call__(self, obj, *args, **kwargs):
        print('Logic here')
        return self.func(obj, *args, **kwargs)

my_decorator = MyDecorator

class MyClass(object):
     @my_decorator
     def my_method(self):
         pass

참고 URL : https://stackoverflow.com/questions/2365701/decorating-python-class-methods-how-do-i-pass-the-instance-to-the-decorator

반응형