【发布时间】:2021-11-15 06:07:43
【问题描述】:
我有一个库证明以下代码:
class LibClass:
def decorator_method(self, *args, **kwargs):
# some code...
pass
打算按如下方式使用:
k = LibClass()
method_args = (,) # something I create
@k.decorator_method(method_args)
def my_func():
# Code that I want to run
具体来说,该库通过这些装饰器实现了一些类似回调的功能。当然,我无法控制该库,也没有任何替代功能。
重要的是,LibClass 的实例是装饰器的一部分,因此 my_func 被添加到该实例 k 的回调中。
但是,我在代码的其他地方实现了my_func,我想将功能与装饰分开。一种方法是像这样创建一个包装器:
k = LibClass()
@k.decorator_method(method_args)
def my_func_wrapper():
# Actual call
my_func()
这种方法按我想要的方式工作,但它的缺点是必须定义和调用并非绝对必要的包装函数。但是,我显然不能直接应用装饰器,因为
def my_func():
# ...
@k.decorator_method(method_args)
my_func
不是有效的 Python 代码。同样,我可能会考虑以这种方式装饰闭包,例如
def my_func_producer(more_args):
def my_func():
# Do something with more_args
return my_func
在哪里
more_args = (,)
@k.decorator_method(method_args)
my_func_producer(more_args)
也是无效的。有什么方法可以应用装饰器而无需定义额外的包装函数?
【问题讨论】:
-
这能回答你的问题吗? how to do a conditional decorator in python
-
“我显然不能直接应用装饰器,”当然你可以。定义
myfunc后,只需执行myfunc = k.decorator_method(method_args)(myfunc)。这就是@语法糖首先要做的事情。 -
装饰器语法只是一个捷径。如果
my_func已经定义,你可以简单地写my_func = k.decorator_method(method_args)(my_func)。如果你的装饰器实际上并没有创建一个新函数,只是用k注册它,你可以省略赋值。 -
顺便说一句,我相信你想要
k.decorator_method(*method_args)而不仅仅是k.decorator_method(method_args)