В чем разница между functools.wraps и update_wrapper - программирование
Подтвердить что ты не робот

В чем разница между functools.wraps и update_wrapper

Я не могу найти, в чем разница между этими двумя функциями python.

functools.wraps и update_wrapper

Может кто-нибудь дать мне пример кода, чтобы я мог понять, в чем разница

4b9b3361

Ответ 1

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)

Ответ 2

Обычно вы просто используете обертки, которые обертывают * update_wrapper *. Подробнее:

  • частичная функция = создать новую функцию с некоторыми аргументами, связанными со значениями

  • обертывает partials * 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