为完整的模块定义Python装饰器

Raj*_*jat 14 python decorator

我有一个包含很多功能的模块(超过25个).我想为每个函数添加一个通用的装饰器函数.通常的做法是在每个函数上面添加一个@decorator行,但我想知道是否有更好的方法可以做到这一点?可能我可以在模块顶部或其他地方声明一个全局装饰器?

请注意,由于我使用的是其他人的代码,我想尽量减少更改的行数,因此修改模块对我来说并不理想.

谢谢.

Joh*_*ooy 14

如果你的装饰师被召唤 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)
Run Code Online (Sandbox Code Playgroud)

您也可以在导入模块后将其应用于模块

import othermodule
import types
for k,v in vars(othermodule).items():
    if isinstance(v, types.FunctionType):
        vars(othermodule)[k] = my_decorator(v)
Run Code Online (Sandbox Code Playgroud)


Ben*_*Ben 7

我认为应用一个装饰器集合,以便你不会明白在哪里寻找有关函数(在其定义中)通常是一个坏主意.明确比隐含更好,所有这一切.

如果你想将装饰器应用于某些第三方模块的功能,而不修改第三方代码,我会这样做:

# 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))
Run Code Online (Sandbox Code Playgroud)

然后在其他地方使用这些功能from my_wrapper_module import some_func_2,等等.

对我来说,这有以下优点:

  1. 无需修改第三方源文件
  2. 从调用网站可以清楚地看到我应该去看看my_wrapper_module我正在调用什么,并且我没有使用未修饰版本的函数
  3. my_wrapper_module导出的函数中可以清楚地看出,它们最初来自哪些函数some_module,并且它们都应用了相同的装饰器
  4. 任何some_module直接导入的代码都不会受到静默和莫名其妙的影响; 如果第三方代码不止一个模块,这可能会特别重要

但是,如果你正在试图做的是破解一个第三方库,这样内部呼叫受到影响,那么这是不是你想要的.