Получить функцию оформления из вложенного декоратора

#python #decorator #python-decorators

Вопрос:

Я пытаюсь получить ссылку на первоначально оформленную функцию из декоратора. Как это можно сделать?

 import inspect
from functools import wraps


def test_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        # the closest I could get to getting the original function:
        # it prints the frame from which the function was called.
        current_frame = inspect.currentframe()
        outer_frames = inspect.getouterframes(current_frame)
        print(outer_frames[-1].frame)
        
        return func(*args, **kwargs)
    return wrapper


@test_decorator
@test_decorator
@test_decorator
def test_func(a, b, c):
    print("func")


test_func(1,2,3)
 

«Первоначально оформленная функция» в этом контексте будет такой test_func , поскольку это целевая функция, которую мы украшаем. Я просмотрел inspect модуль, самое близкое, что я мог получить, — это получить первый кадр в стеке, но это не сильно помогает.

Может быть, в stdlib уже есть решение?

Комментарии:

1. Разве это не просто func в вашем случае? Попробуйте добавить print("It's me:", func) под def wrapper(...):

2. @Рафаэль-ВО нет, к сожалению, это не так. Декораторы складываются стопкой, но друг на друге. Очевидно, что единственный, кто видит настоящее func , — последний @test_decorator .

3. @Rafael-WO на самом деле это проблема, которую я пытаюсь решить. Чтобы увидеть исходную функцию от любого декоратора в стеке.

Ответ №1:

Этот:

https://github.com/micheles/decorator

 import inspect
from decorator import decorator


@decorator
def test_decorator(func, *args, **kwargs):
    print(inspect.getfullargspec(func))
    return func(*args, **kwargs)


@test_decorator
@test_decorator
@test_decorator
def test_func(a, b, c):
    print("func")


test_func(1,2,3)
 

Теперь изнутри каждого test_decorator он печатает:

 FullArgSpec(args=['a', 'b', 'c'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
 

Благослови господь этого человека, написавшего модуль, этот парень-легенда.