我想创建一个新的装饰器来代替@wraps(f)
,它可以做任何魔术@wraps(f)
以及其他什么。我该怎么办?
具体来说,我有几个装饰形式:
def decorator(f):
@wraps(f)
def wrapper(*args, **kwargs):
# does some stuff in here
return f(*args, **kwargs)
if not hasattr(wrapper, '_first_line'):
wrapper._first_line = inspect.getsourcelines(f)[1]
return wrapper
看起来我应该能够创建一个像@wraps_with_first_line(f)
这样的装饰器,它将完成@wraps(f)
和if not hasattr(wrapper, '_first_line'): wrapper._first_line = inspect.getsourcelines(f)[1]
所做的一切。
如果要添加的内容不是包装对象的属性,则可以使用:
def wraps_with_first_line(f):
def wrap(wrapper):
wrapper = wraps(f)(wrapper)
if not hasattr(wrapper, '_first_line'):
wrapper._first_line = inspect.getsourcelines(f)[1]
return wrapper
return wrap
如果它已经是包装对象的属性,请使用Sven的方法。
您应该遵循添加指向包装函数的__wrapped__
属性的良好做法,而不是添加该包装函数的单个属性。 New versions的functools.wraps()
会自动执行此操作,但如果您使用的是旧版本的Python而不是3.2,您可以轻松扩展wraps()
以添加__wrapped__
:
def my_wraps(wrapped, **kwargs):
def decorator(wrapper):
functools.update_wrapper(wrapper, wrapped, **kwargs)
wrapper.__wrapped__ = wrapped
return decorator
编辑:这是一个从可能的多重装饰函数中提取原始函数的函数:
def orig_function(f):
try:
while True:
f = f.__wrapped__
except AttributeError:
return f