Domanda

Voglio costruire le classi per l'uso come decoratori con i seguenti principi intatta:

  1. Dovrebbe essere possibile impilare più tali decoratori di classe 1 sulla parte superiore fuori funzione.
  2. Il puntatore nome della funzione risultante dovrebbe essere indistinguibile dalla stessa funzione, senza un decoratore, salvo forse solo per il tipo / classe è.
  3. ordinare dal decoratori non dovrebbero essere rilevanti se non in realtà mandato dai decoratori. Vale a dire. decoratori indipendenti potrebbero essere applicati in qualsiasi ordine.

Questo è per un progetto Django, e il caso specifico sto lavorando ora il metodo ha bisogno 2 decoratori, e di apparire come una funzione Python normale:

@AccessCheck
@AutoTemplate
def view(request, item_id) {}

@AutoTemplate cambia la funzione in modo che invece di restituire un HttpResponse, semplicemente restituisce un dizionario per l'utilizzo nel contesto. Un RequestContext viene utilizzato, e il nome del modello è dedotto dal nome del metodo e il modulo.

@AccessCheck aggiunge ulteriori controlli per l'utente in base alla item_id.

Sono indovinando è solo per ottenere il giusto costruttore e copiare gli attributi appropriati, ma che gli attributi sono?

Il seguente decoratore non funziona come ho descritto:

class NullDecl (object):
    def __init__ (self, func):
        self.func = func
    def __call__ (self, * args):
        return self.func (*args)

Come dimostra il seguente codice:

@NullDecl
@NullDecl
def decorated():
    pass

def pure():
    pass

# results in set(['func_closure', 'func_dict', '__get__', 'func_name',
# 'func_defaults', '__name__', 'func_code', 'func_doc', 'func_globals'])
print set(dir(pure)) - set(dir(decorated));

Inoltre, cercare e aggiungere nel costruttore NullDecl, e si lavorerà per la prima decoratore, ma non il secondo "Funz Stampa nome ." -. Il nome mancheranno

Raffinato eduffy s 'rispondere un po', e sembra funzionare abbastanza bene:

class NullDecl (object):
    def __init__ (self, func):
        self.func = func
        for n in set(dir(func)) - set(dir(self)):
            setattr(self, n, getattr(func, n))

    def __call__ (self, * args):
        return self.func (*args)
    def __repr__(self):
        return self.func
È stato utile?

Soluzione

Una classe decoratore do-nothing sarebbe simile a questa:

class NullDecl (object):
   def __init__ (self, func):
      self.func = func
      for name in set(dir(func)) - set(dir(self)):
        setattr(self, name, getattr(func, name))

   def __call__ (self, *args):
      return self.func (*args)

E allora si può applicare normalmente:

@NullDecl
def myFunc (x,y,z):
   return (x+y)/z

Altri suggerimenti

Il decoratore modulo vi aiuta a scrivere decoratori firma-conservazione.

E il PythonDecoratorLibrary potrebbe fornire utili esempi per decoratori.

Per creare un decoratore che avvolge le funzioni in una questione che li rendono indistinguibile dalla funzione originale, utilizzare functools.wraps.

Esempio:


def mydecorator(func):
    @functools.wraps(func):
    def _mydecorator(*args, **kwargs):
        do_something()
        try:
            return func(*args, **kwargs)
        finally:
            clean_up()
    return _mydecorator

# ... and with parameters
def mydecorator(param1, param2):
    def _mydecorator(func):
        @functools.wraps(func)
        def __mydecorator(*args, **kwargs):
            do_something(param1, param2)
            try:
                return func(*args, **kwargs)
            finally:
                clean_up()
        return __mydecorator
    return _mydecorator

(la mia preferenza personale è quello di creare decoratori utilizzando le funzioni, non classi)

L'ordinamento dei decoratori è la seguente:


@d1
@d2
def func():
    pass

# is equivalent to
def func():
    pass

func = d1(d2(func))
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top