Wie kann ich eine Instanz der Klasse Variable als Argument für eine Methode Dekorateur in Python verwenden?
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()
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.