从嵌套装饰器中获取装饰函数



我试图从装饰器内获得对原始装饰函数的引用。如何做到这一点?

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?

This:

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={})

祝福这个写模块的人,他是一个传奇。

受@Jorge E. Cardona评论的启发,我最终做了以下事情:

from functools import wraps
import inspect
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):

wraped_func = func

while hasattr(wraped_func, "__wrapped__"):
wraped_func = wraped_func.__wrapped__
print(inspect.getfullargspec(wraped_func))
return func(*args, **kwargs)
return wrapper
@decorator
@decorator
@decorator
def decorated_func(arg1, arg2):
...

现在如果你调用,decorated_func:

decorated_func(1, 2)

输出将是:

FullArgSpec(args=['arg1', 'arg2'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
FullArgSpec(args=['arg1', 'arg2'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
FullArgSpec(args=['arg1', 'arg2'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})

每个被调用的装饰器的打印。

最新更新