2013-03-12 13 views
14

Non riesco a trovare qual è la differenza tra queste due funzioni Python.Qual è la differenza tra functools.wraps e update_wrapper

functools.wraps e update_wrapper

Può qualcuno darmi qualche esempio di codice in modo che io possa capire che cosa è la differenza

+1

Hai provato leggendo la documentazione? – ecatmur

+1

ho letto i documenti ma questo era confuso, mi sembrano entrambi, ma non ho capito la chiarezza – user1865341

+0

Sono d'accordo con l'OP su come i documenti siano confusi. –

risposta

12

functools.wraps è equivalente a:

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

In realtà è implementato usando partial invece di una funzione interiore, ma l'effetto è lo stesso.

Lo scopo è quello di consentire di utilizzarlo come decoratore:

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

è equivalente a:

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

Normalmente si basta usare impacchi, che avvolge * update_wrapper *. Più:

  • parziale ing funzione = creare una nuova funzione con alcuni argomenti legati ai valori

  • wraps partial * update_wrapper * con avvolti, creando così un decoratore per avvolgitore

  • * update_wrapper * ha lo scopo di copiare determinati attributi (non argomenti) da spostato da a involucro. Su di default sono:

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

Un esempio utile:

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 
Problemi correlati