26

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

functools.wrapsupdate_wrapper

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

4

2 回答 2

22

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)
于 2013-03-12T10:00:00.060 回答
9

通常你只会使用包装*update_wrapper* 的 wraps 。更多的:

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

  • 用Wrapper包裹partials *update_wrapper* ,从而为wrapper创建一个装饰器

  • *update_wrapper* 's purpose is to copy certain attributes (not arguments) from wrapped to wrapper. On default these are:

WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__',
                       '__annotations__')
WRAPPER_UPDATES = ('__dict__',)

A useful example:

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
于 2013-09-27T15:13:10.427 回答