Выполнение исходной функции от каждого декоратора с использованием нескольких декораторов в python

Ниже приведен упрощенный пример того, что я пытаюсь сделать. Функция «print_number» ниже обернута двумя декораторами.

def another_decorator(function):
    def wrapper(*arg, **kwargs):
        ret = function(*arg, **kwargs)
        print(ret, "executed from another_decorator")
    return wrapper

def test_decorator(function):
    def wrapper(*arg, **kwargs):
        ret = function(*arg, **kwargs)
        print(ret, "executed from test_decorator")
    return wrapper

@another_decorator
@test_decorator
def print_number(num):
    return num
x = print_number(222)
print(x)

Вышеуказанное возвращает

222 executed from test_decorator
None executed from another_decorator
None

Как видите, только test_decorator смог выполнить обернутую функцию print_number. Вызов этой функции был полностью пропущен в файле Another_decorator. Некоторый контекст о том, почему мне это нужно. У меня есть код, в котором я оборачиваю основную асинхронную функцию несколькими декораторами, где мне нужно вызывать асинхронную функцию каждым декоратором. Каждый декоратор выполняет некоторую предварительную работу, чтобы перейти к вызываемой асинхронной функции, где создается сеанс aiohttp и планируется сопрограмма с использованием sure_future. Есть ли способ или возможная процедура для вызова обернутой функции «функция» из каждого декоратора?


person user2993021    schedule 21.09.2017    source источник
comment
Вы нашли решение этой проблемы?   -  person Ajay Maity    schedule 19.09.2019


Ответы (1)


вам нужно на самом деле вернуться в ваших декораторах.. Кроме того, функции - это просто объекты в python, поэтому дайте вашей функции-оболочке атрибут "оригинал"

def another_decorator(function):
    def wrapper(*arg, **kwargs):
        ret = function(*arg, **kwargs)
        print(ret, "executed from another_decorator")
        return ret
    wrapper.original = getattr(function,"original",function)
    return wrapper

def test_decorator(function):
    def wrapper(*arg, **kwargs):
        ret = function(*arg, **kwargs)
        print(ret, "executed from test_decorator")
        return ret
    wrapper.original = getattr(function,"original",function)
    return wrapper
person Joran Beasley    schedule 21.09.2017
comment
Спасибо. Это действительно интересно, и это действительно работает, хотя мне трудно понять, что здесь происходит. Я понимаю, что в getattr вы получаете значение «функция» по умолчанию, поскольку «оригинал» не существует в объекте «функция». Я нерешительно допускаю, что извлечение значения «выполняет» функцию и вызывается функция «print_number». Но я не очень понимаю, почему это работает. Раньше я использовал functool.wraps и пытался выполнить function.__wrapped__() в 'another_decorator', но это не сработало. - person user2993021; 22.09.2017