functools.wraps和update_wrapper有什么区别

时间:2013-03-12 09:42:36

标签: python

我无法找到这两个python函数之间的区别。

functools.wrapsupdate_wrapper

有些人可以给我一些代码示例,以便我能理解有什么区别

2 个答案:

答案 0 :(得分:13)

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)

答案 1 :(得分:7)

通常你会使用 wrap ,它包装了* update_wrapper *。更多:

  • 部分一个函数=创建一个新函数,其中一些参数绑定到值

  • 包裹包裹部分* update_wrapper *,从而为包装创建装饰器

  • * update_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