【问题标题】:Member function decorator and self argument成员函数装饰器和自变量
【发布时间】:2019-01-14 07:39:45
【问题描述】:

以下成员函数上的装饰器的最小示例:

def wrap_function(func):
    def wrapper(*args, **kwargs):
        print(args)
        print(kwargs)
    return wrapper

class Foo:
    @wrap_function
    def mem_fun(self, msg):
        pass

foo = Foo()
foo.mem_fun('hi')

输出:

(<__main__.Foo object at 0x7fb294939898>, 'hi')
{}

所以selfargs 之一。

但是,当使用包装类时:

class WrappedFunction:
    def __init__(self, func):
        self._func = func

    def __call__(self, *args, **kwargs):
        print(args)
        print(kwargs)

def wrap_function(func):
    return WrappedFunction(func)

class Foo:
    @wrap_function
    def mem_fun(self, msg):
        pass

foo = Foo()
foo.mem_fun('hi')

输出是:

('hi',)
{}

因此,引用Foo 对象的selfWrappedFunction 对象的__call__ 的主体中是不可访问的。

我怎样才能让它在那里访问?

【问题讨论】:

    标签: python python-3.x decorator wrapper member-functions


    【解决方案1】:

    很遗憾,但这可能是您在__call__ 函数中需要它的唯一解决方案。 建议检查一下:What is the difference between __init__ and __call__ in Python?

    def wrap_function(func):
        def wrapper(*args, **kwargs):
            x = WrappedFunction(func)
            x(*args, **kwargs)
        return wrapper
    

    【讨论】:

      【解决方案2】:

      通过包装函数逻辑(但不是实例)并将其重定向到类实例,您将丢失对 bounded 实例的引用 - 此时,类实​​例自己的 self应用而不是包装的实例方法,因为它会在中间装饰器中丢失 (wrap_function())。

      您要么必须包装对包装函数的调用并将*args/**kwargs 传递给它,要么只创建一个适当的包装类而不是添加中间包装:

      class WrappedFunction(object):
      
          def __call__(self, func):
              def wrapper(*args, **kwargs):
                  print(args)
                  print(kwargs)
                  # NOTE: `WrappedFunction` instance is available in `self`
              return wrapper
      
      class Foo:
          @WrappedFunction()  # wrap directly, without an intermediary
          def mem_fun(self, msg):
              pass
      
      foo = Foo()
      foo.mem_fun('hi')
      # (<__main__.Foo object at 0x000001A2216CDBA8>, 'hi')
      # {}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-01-25
        • 1970-01-01
        • 1970-01-01
        • 2020-05-02
        • 1970-01-01
        • 1970-01-01
        • 2018-04-07
        • 2018-05-01
        相关资源
        最近更新 更多