【问题标题】:Decorator to convert an instance method into a class function装饰器将实例方法转换为类函数
【发布时间】:2014-09-05 19:16:55
【问题描述】:

我需要将几个方法作为回调传递,它们不采用self 参数。这是我当前代码的样子:

def _do_callback(callback, log, *args):
    try:
        # some common code
        callback(*args)
    except:
        log.error('XX')

class Foo(object):
    def __init__(self):
        self.log = Log('Foo')
        self.cb1_wrapper = lambda x: _do_callback(self.cb1, self.log, x)  # I need a function taking one parameter
        self.cb2_wrapper = lambda x: _do_callback(self.cb2, self.log, x)

    def cb1(self, x):
        # some code accessing self

    def cb2(self, x):
        # some code accessing self

    def register_callbacks(self):
        register('1', self.cb1_wrapper)
        register('2', self.cb2_wrapper)

是否可以编写一些装饰器应用于cb1cb2,以便能够将结果传递到当前采用self.cb1_wrapper 的代码中?

(我知道标题不太理想,请随意编辑)

【问题讨论】:

  • 您的意思是要使用装饰器将方法注册为回调?你不能为此使用装饰器,因为应用装饰器时没有实例。
  • @MartijnPieters 很好,实际上我想简化代码。如果您不考虑实现,使用装饰器似乎是正确的,所以我认为也许有一个解决方案。
  • 听起来你的问题是How to use decorator in observer pattern for Python 2.7的欺骗。

标签: python class decorator python-decorators


【解决方案1】:

当然;想想一个展开的方法应该是什么样子:

def callback(fn):
    def inner(self, *args):
        return _do_callback(fn.__get__(self, type(self)), self.log, *args)
    return inner

class Foo(object):
    def __init__(self):
        self.log = Log('Foo')

    @callback
    def cb1_wrapped(self, x):
        pass

【讨论】:

  • @callback 返回一个仍然需要 self 的函数,不是吗?
  • @wRAR 当然,这就是你想要的:见stackoverflow.com/questions/1367514/…
  • @wRAR:这仍然需要您在实例上注册方法;你会使用Foo().cb1_wrapped,它会返回一个绑定方法,在调用时为你传入self。这就是回调的全部内容,您需要注册 bound 方法。
  • 哦,我在同一个类的方法中注册了回调(代码示例已更新),所以看起来问题容易多了?
【解决方案2】:

我不了解装饰器,但您可以轻松编写一个“包装函数”,将 绑定方法 转换为“回调”。 类似的东西:

def wrap(bound_method):
    return lambda x: _do_callback(bound_method, bound_method.__self__.log, x)

一个(主要?)缺点是您必须在调用时使用包装器:

foo = Foo()
...
my_fnc_using_callback(wrap(foo.cb1))

【讨论】:

    猜你喜欢
    • 2021-04-21
    • 2019-02-03
    • 2017-11-12
    相关资源
    最近更新 更多