Wie kann ich eine Instanz der Klasse Variable als Argument für eine Methode Dekorateur in Python verwenden?

StackOverflow https://stackoverflow.com/questions/1231950

  •  22-07-2019
  •  | 
  •  

Frage

Wie kann ich eine Instanz der Klasse Variable als Argument für eine Methode Dekorateur in Python verwenden? Im Folgenden ist ein minimales Beispiel zeigt, was ich versuche zu tun. Es scheitert offenbar als die Dekorateur Funktion Zugriff auf die Referenz muss nicht auf die Instanz, und ich habe keine Ahnung, wie aus dem Dekorateur Zugriff auf die Referenz zu erhalten.

def decorator1(arg1):
    def wrapper(function):
        print "decorator argument: %s" % arg1
        return function
    return wrapper

class Foo(object):
    def __init__(self, arg1):
        self.var1 = arg1

    @decorator1(self.var1)
    def method1(self):
        print "method1"

foo = Foo("abc")
foo.method1()
War es hilfreich?

Lösung

Es wird nicht funktionieren; der Dekorateur während Klasse Schöpfung Zeit bezeichnet, die lange bevor eine Instanz erstellt (, wenn , die jemals passiert). Also, wenn Ihr „Dekorateur“ die Instanz braucht, haben Sie die „Dekoration“ bei der Instanziierung Zeit zu tun:

def get_decorator(arg1):
    def my_decorator(function):
        print "get_decorator argument: %s" % arg1
        return function
    return my_decorator

class Foo(object):
    def __init__(self, arg1):
        self.var1 = arg1
        self.method1 = get_decorator(self.var1)(self.method1)

    def method1(self):
        print "method1"

foo = Foo("abc")
foo.method1()

Beachten Sie, dass ich die Funktionsnamen geändert entsprechend ihrer Bedeutungen; der eigentliche „Dekorateur“, das heißt die Funktion, die (potentiell) das Verfahren modifiziert, wrapper in Ihrem Fall ist, nicht decorator1.

Andere Tipps

Ihre „Schär“ Funktion ist eigentlich ein Dekorateur, anstatt eine Schär. Ihre „decorator1“ -Funktion ist ein Dekorateur Konstruktor. Wenn Sie Zugriff auf self.var1 in Runtime haben wollen, müssen Sie eine Schär nicht Dekorateur machen:

def decorator(function):
  def wrapper(self,*args,**kwargs):
    print "Doing something with self.var1==%s" % self.var1
    return function(self,*args,**kwargs)
  return wrapper

class Foo(object):
  def __init__(self, arg1):
    self.var1 = arg1

  @decorator
  def method1(self):
    print "method1"

foo = Foo("abc")
foo.method1()

Wenn Sie allgemeinere Dekorateur haben wollen, ist es besser, Idee, eine aufrufbare Klasse zu deklarieren:

class decorator:
  def __init__(self,varname):
      self.varname = varname
  def __call__(self,function):
    varname=self.varname
    def wrapper(self,*args,**kwargs):
      print "Doing something with self.%s==%s" % (varname,getattr(self,varname))
      return function(self,*args,**kwargs)
    return wrapper

Mit:

  @decorator("var1")

Der Dekorateur ausgeführt wird, wenn die Klasse definiert ist, so dass Sie nicht eine Instanzvariable, um es passieren können.

Hier ist, wie wir dies in den alten Tagen zu tun, verwendet wird.

class Foo(object):
    def __init__(self, arg1):
        self.var1 = arg1

    def method1(self):
        self.lock()
        try:
            self.do_method1()
        except Exception:
            pass # Might want to log this
        finally:
            self.unlock()

    def do_method1(self):
        print "method1"

    def lock(self):
        print "locking: %s" % self.arg1

    def unlock(self):
        print "unlocking: %s" % self.arg1

Nun muss eine Unterklasse nur o Überschreibung do_method1 die Vorteile der „Verpackung“ zu erhalten. Fertig, um die alte Art und Weise, ohne with Aussage.

Ja, es ist langatmig. Es ist jedoch keine Magie beinhalten, auch nicht.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top