2013-03-12 15 views
14

Nie jestem w stanie znaleźć różnicę między tymi dwoma funkcjami python.Jaka jest różnica między functools.wraps a update_wrapper

functools.wraps i update_wrapper

Można niektóre dać mi jakiś przykład kodu tak, że mogę zrozumieć, co jest różnica

+1

Czy próbowałeś czytanie dokumentacji? – ecatmur

+1

Czytałem dokumentację, ale to było mylące, wyglądają tak samo dla mnie, ale nie do końca zrozumiałe wtedy jasność – user1865341

+0

Zgadzam się z OP o dokumentach wprowadzających w błąd. –

Odpowiedz

12

functools.wraps odpowiada:

def wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES): 
    def decorator(wrapper): 
     return update_wrapper(wrapper, wrapped=wrapped, ...) 
    return decorator 

To rzeczywiście realizowane z wykorzystaniem partial zamiast funkcja wewnętrzna, ale efekt jest taki sam.

Celem jest umożliwienie używania go jako dekorator:

@wraps(f) 
def g(): 
    ... 

odpowiada:

def g(): 
    ... 
g = update_wrapper(g, f) 
6

Zwykle wystarczy użyć okłady, które owija * update_wrapper *. Więcej:

  • częściowy ing = funkcja tworzenia nowej funkcji w przypadku niektórych argumentów związane z wartościami

  • okładów partials * update_wrapper * z zawinięte, tworząc dekorator dla opakowaniu

  • * celem update_wrapper * jest skopiowanie pewnych atrybutów (nie argumentów) z zapakowane w opakowaniu do . Na domyślnie są to:

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

Przydatny przykład:

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 
Powiązane problemy