Frage

Ich möchte Klassen für so Dekorateure mit den folgenden Grundsätzen Gebrauch konstruieren intakt:

  1. Es sollte möglich sein, mehrere solche Klasse Dekorateure auf off 1 Funktion zu stapeln.
  2. Die resultierenden Funktionsnamen Zeiger sollten ohne Dekorateur aus der gleichen Funktion nicht zu unterscheiden sein, außer vielleicht für nur welche Art / Klasse ist.
  3. die Dekorateure Bestellung aus nicht relevant sein sollte, es sei denn, tatsächlich von den Dekorateuren beauftragt. D. h. unabhängige Dekorateure in beliebiger Reihenfolge angewandt werden könnten.

Dies ist für ein Django-Projekt, und der spezielle Fall arbeite ich jetzt auf das Verfahren benötigt 2 Dekorateure, und als eine normale Python-Funktion angezeigt werden:

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

@AutoTemplate ändert sich die Funktion, so dass stattdessen eine Httpresponse zurückzukehren, es ist nur ein Wörterbuch zur Verwendung kehrt in den Kontext. Ein Request verwendet wird, und der Vorlagenname wird aus dem Methodennamen und Modul zu entnehmen.

@AccessCheck fügt zusätzliche Kontrollen der Benutzer auf der Grundlage der item_id.

Ich vermute, es ist nur der Konstruktor richtig zu machen und die entsprechenden Attribute kopieren, aber welche Attribute sind diese?

Das folgende Dekorateur wird nicht funktionieren, wie ich beschreiben:

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

Wie der folgende Code demonstriert:

@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));

Darüber hinaus versuchen, und fügen Sie im NullDecl Konstruktor, und es wird zum ersten Dekorateur arbeiten, aber nicht die zweite "print Func Namen .." - als Name fehlt wird

Refined eduffy 's ein wenig beantworten, und es scheint ziemlich gut zu funktionieren:

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
War es hilfreich?

Lösung

Eine do-nothing Dekorateur Klasse würde wie folgt aussehen:

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)

Und dann kann man es gilt in der Regel:

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

Andere Tipps

Die Dekorateur Modul hilft Ihnen das Schreiben Signatur erhalt Dekorateure.

Und die PythonDecoratorLibrary könnten nützliche Beispiele für Dekorateure bieten.

einen Dekorateur zu erstellen, die Funktionen in einer Angelegenheit Wraps, die sie nicht mehr von der ursprünglichen Funktion zu machen, verwenden Sie functools.wraps.

Beispiel:


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

(meine persönliche Präferenz ist Dekorateure mit Funktionen zu erstellen, nicht Klassen)

Die Bestellung von Dekorateure ist wie folgt:


@d1
@d2
def func():
    pass

# is equivalent to
def func():
    pass

func = d1(d2(func))
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top