我试图从装饰器内获得对原始装饰函数的引用。如何做到这一点?
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={})
每个被调用的装饰器的打印。