Подтвердить что ты не робот

Определение декораторов Python для полного модуля

У меня есть модуль, который содержит много функций (более 25). Я хочу добавить общую функцию декоратора к каждой из этих функций. Обычный способ - добавить строку @decorator над каждой функцией, но мне было интересно, есть ли лучший способ сделать это? Возможно, я могу объявить глобальный декоратор в верхней части модуля или что-то еще?

Обратите внимание, что, поскольку я использую код другого пользователя, я хочу свести к минимуму количество измененных строк, поэтому изменение модуля не идеально для меня.

Спасибо.

4b9b3361

Ответ 1

Если ваш декоратор называется 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)

Ответ 2

Я думаю, что применение декоратора en-masse, так что не очевидно, где вы будете искать, чтобы узнать о функции (по ее определению), как правило, плохая идея. Явный лучше, чем неявный, и все такое.

Если вы хотите применить декоратор к некоторым функциям модуля третьей стороны, не изменяя сторонний код, вот как я это сделаю:

# 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 напрямую, не является бесшумным и необъяснимым; это может быть особенно важно, если сторонний код содержит более одного модуля.

Но если то, что вы пытаетесь сделать, это взломать стороннюю библиотеку, чтобы повлиять на внутренние вызовы, тогда это не то, что вы хотите.