functools.wraps和update_wrapper有什么区别
我找不到这两个Python函数之间的区别。
functools.wraps
和 update_wrapper
有人能给我一些代码示例,让我明白它们之间的区别吗?
2 个回答
10
通常你会使用 wraps,它是用来包装 *update_wrapper* 的。下面是一些详细信息:
partial 一个函数 = 创建一个新函数,并把一些参数固定为特定的值
wraps 会用 wrapper 来更新 *update_wrapper*,这样就创建了一个装饰器,用于 wrapper
*update_wrapper* 的目的是把某些属性(不是参数)从 wrapped 复制到 wrapper。默认情况下,这些属性包括:
WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__', '__annotations__') WRAPPER_UPDATES = ('__dict__',)
一个有用的例子:
try:
from itertools import izip_longest as zip_longest
except:
from itertools import zip_longest
from collections import Iterable
from functools import wraps
def ziplongest(*args):
'''zip_longest with last element as filler
>>> args=([9],[2,3],1)
>>> [t for t in ziplongest(*args)]
[(9, 2, 1), (9, 3, 1)]
'''
iterable = lambda a:(a if isinstance(a,Iterable) else [a])
_args = [iterable(a) for a in args]
withnone = zip_longest(*_args)
for e in withnone:
yield tuple((en or _args[i][-1]) for i,en in enumerate(e))
def listable(f):
'''apply f to list members
>>> @listable
... def mul(a,b):
... 'returns a*b'
... return a*b
>>> mul(2,[3,9])
[6, 18]
>>> mul.__doc__
'returns a*b'
'''
@wraps(f)#without this e.g __doc__ would get hidden
def to_elems(*args,**kwargs):
if any(isinstance(x,list) for x in args):
return [f(*a,**kwargs) for a in ziplongest(*args)]
else:
return f(*args,**kwargs)
return to_elems
25
functools.wraps
的作用和下面的内容是一样的:
def wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES):
def decorator(wrapper):
return update_wrapper(wrapper, wrapped=wrapped, ...)
return decorator
它实际上是用 partial
来实现的,而不是用内部函数,但效果是一样的。
它的目的是为了让我们可以把它当作装饰器来使用:
@wraps(f)
def g():
...
这和下面的内容是等价的:
def g():
...
g = update_wrapper(g, f)