Python Decorators

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
samid
User
Beiträge: 60
Registriert: Samstag 28. April 2012, 08:40

Hallo zusammen,

kann mir den jemand sagen, welchen Vorteil ich habe wenn ich einen Decorator einsetze und in welchen Fällen in diesen einsetzen sollte. Ich hätte z.B. zur Zeit einen Fall, bei dem ich eine bereits definierte Funktion habe, und diese Funktion würde ich gerne modifizieren, diese sollte aber trotzdem unter dem gleichen Namen laufen, das kann ich aber mit einem Decorator nicht lösen, denn einen Decorator nutze ich doch bei der Erstellung der Funktion oder?

Mein Beispiel:

Ursprungsfunktion --> object.save() --> Das Objekt wird gespeichert
Nach dem Modifizieren der bestehenden Funktion „save()“ sollte diese trotzdem mit object.save() aufgerufen werden. Kann ich sowas mit Decoratoren lösen?

Gruß
Samid
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@samid: Meinst Du sowas?

Code: Alles auswählen

In [1]: def about_to_bark(f):
   ...:     def wrapper(*args):
   ...:         print 'dog about to bark: ' + args[0].nick
   ...:         return f(*args)
   ...:     return wrapper
   ...: 

In [2]: class Dog(object):
   ...:     def __init__(self, nick):
   ...:         self.nick = nick
   ...:     @about_to_bark
   ...:     def bark(self):
   ...:         print 'Woof woof!'
   ...:         

In [3]: dog = Dog('Snoopie')

In [4]: dog.bark()
dog about to bark: Snoopie
Woof woof!
samid
User
Beiträge: 60
Registriert: Samstag 28. April 2012, 08:40

Genau hier ist ja auch der Knackpunkt, du verwendest den Decorator bei der Erstellung einer neuen Funktion. Wie gehe ich aber vor wenn die Funktion bereits
definiert ist, und ich diese bestehende Funktion modifizieren will, dann aber die mod. Funktion mit demselben Namen aufrufe?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ein Decorator ist nichts anderes als eine Funktion, du kannst den daher auch genau so benutzen:

Code: Alles auswählen

>>> class Spam(object):
...     def spam(self, x):
...         print x
... 
>>> s = Spam()
>>> s.spam(42)
42
>>> def my_fancy_decorator(func):
...     def f(self, x):
...         return 2*x
...     return f
... 
>>> Spam.spam = my_fancy_decorator(Spam.spam)                         
>>> s.spam(42)
84
Das Ergebnis des Decorators bindest du einfach an den Namen der alten Methode und schon hast du sie überschrieben.
Das Leben ist wie ein Tennisball.
samid
User
Beiträge: 60
Registriert: Samstag 28. April 2012, 08:40

Super, genau das habe ich gesucht. Danke.
Aber den Syntaxausdruck:

@wrapper
.....

kann ich nur bei der Bildung einer neuen Funktion verwenden?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Richtig, die @-Syntax wird dann aber ganz einfach übersetzt. Aus

Code: Alles auswählen

@wrapper
def func(...):
    ...
wird intern

Code: Alles auswählen

def func(...):
    ...

func = wrapper(func)
Also nichts anderes als in meinem Beispiel. Vielleicht schaust du dir dazu einfach mal das entsprechende PEP an, da wird noch etwas mehr erläutert.
Das Leben ist wie ein Tennisball.
Antworten