【发布时间】:2012-02-15 15:08:42
【问题描述】:
我有一个包含很多功能(超过 25 个)的模块。我想为这些函数中的每一个添加一个通用的装饰器函数。正常的做法是在每个函数上方添加一个@decorator 行,但我想知道是否有更好的方法来做到这一点?也许我可以在模块顶部或其他地方声明一个全局装饰器?
请注意,由于我使用的是别人的代码,我想尽量减少更改的行数,所以修改模块对我来说并不理想。
谢谢。
【问题讨论】:
我有一个包含很多功能(超过 25 个)的模块。我想为这些函数中的每一个添加一个通用的装饰器函数。正常的做法是在每个函数上方添加一个@decorator 行,但我想知道是否有更好的方法来做到这一点?也许我可以在模块顶部或其他地方声明一个全局装饰器?
请注意,由于我使用的是别人的代码,我想尽量减少更改的行数,所以修改模块对我来说并不理想。
谢谢。
【问题讨论】:
如果你的装饰器被称为my_decorator
### Decorate all the above functions
import types
for k,v in globals().items():
if isinstance(v, types.FunctionType):
globals()[k] = my_decorator(v)
您也可以在导入后将其应用于模块
import othermodule
import types
for k,v in vars(othermodule).items():
if isinstance(v, types.FunctionType):
vars(othermodule)[k] = my_decorator(v)
【讨论】:
我认为整体应用装饰器,这样你会去哪里寻找函数(在其定义中)并不明显,这通常是一个坏主意。显式优于隐式,等等。
如果你想在不修改第三方代码的情况下将装饰器应用于某些第三方模块的功能,我会这样做:
# my_wrapper_module.py
import some_module
import functools
def some_decorator(func):
@functools.wraps(func):
def wrapper(*args, **kwargs):
...
return wrapper
FUNCTION_NAMES = [
'some_func_1',
'some_func_2',
'some_func_3',
...
]
for name in FUNCTION_NAMES:
globals()[name] = some_decorator(getattr(some_module, name))
然后通过from my_wrapper_module import some_func_2等在其他地方使用这些功能。
对我来说,这有以下优点:
my_wrapper_module 以了解我在调用什么,并且我没有使用未修饰版本的函数my_wrapper_module 可以清楚地看出正在导出哪些函数,它们最初来自 some_module,并且它们都应用了相同的装饰器some_module 的代码都不会受到静默和莫名其妙的影响;如果第三方代码不止一个模块,这一点尤其重要但是,如果您尝试破解第三方库以影响内部调用,那么这不是您想要的。
【讨论】:
wrapper_module的想法。顺便说一句,我已经删除了我的答案(因为@gnibbler's 更完整并且对函数类型有正确的检查)。