将实例方法转换为类函数的装饰器

1 投票
2 回答
1623 浏览
提问于 2025-04-18 13:24

我需要传递几个方法作为回调,但这些方法不需要 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 的代码?

(我知道标题不是很好,欢迎修改)

2 个回答

0

我对装饰器不太了解,但你可以很简单地写一个“包装函数”,把一个绑定方法变成一个“回调”。大概是这样的:

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))
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

撰写回答