funktion = dec1(dec2(funktion)) <[Da stimmt doch was nic

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
cullmann
User
Beiträge: 13
Registriert: Donnerstag 10. April 2008, 19:08
Wohnort: Dublin

Servus alle zusammen,

bin noch ein Python anfänger aber das hier was ich in dem open book von Galileo gefunden habe kannd doch echt net sein, raff echt net wie das gehen soll:

... Kapitel 13.9.... Galileo computing Python
Function Decorator können nicht nur auf Methoden angewendet werden, sondern genauso auf Funktionen. Zudem können sie ineinander verschachtelt werden, wie folgendes Beispiel zeigt:

@dec1
@dec2
def funktion():
pass

Diese Funktionsdefinition ist äquivalent zu folgendem Code:

def funktion():
pass
funktion = dec1(dec2(funktion))

Es erübrigt sich zu sagen, dass sowohl dec1 als auch dec2 implementiert werden müssen, bevor die Beispiele lauffähig sind.

.... (ZITAT Ende)


Also entweder ist mir da was wesentliches entgangen oder das stimmt was nicht.


Danke schonmal im vorraus.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Dann ist dir wohl etwas wesentliches entgangen.
cullmann
User
Beiträge: 13
Registriert: Donnerstag 10. April 2008, 19:08
Wohnort: Dublin

super danke, bist nen fuchs!

Hab gemerkt wo mein denkfehler war, hab angenommen dec1 /dec2 sind ebenfalls functions, habe gedachte diese function decoration sind so angelegt wie die delegates in C#.
Aber dank dem guten Learning Python von OReilly hab ich es jetzt doch geschnallt.


cullmann
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

"dec1" und "dec2" sind ja auch Funktionen, diese modifizieren allerdings die übergebene Funktion "function" oder erweitern diese. Es wird hier allerdings keine Funktionskomposition von "dec1", "dec2" und "function" durchgeführt, sondern nur von "dec1" und "dec2". Letztere wird dann mit dem Parameter "function" aufgerufen.
cullmann
User
Beiträge: 13
Registriert: Donnerstag 10. April 2008, 19:08
Wohnort: Dublin

Hmm so wie ich das jetzt aber verstanden habe handelt es ich um die Deco-ding um referencen auf klassen:

Code: Alles auswählen

class tracer:
def _ _init_ _(self, func):
self.calls = 0
self.func = func
def _ _call_ _(self, *args):
self.calls += 1
print 'call %s to %s' % (self.calls, self.func._ _name_ _)
self.func(*args)
@tracer
def spam(a, b, c): # Wrap spam in a decorator object
print a, b, c
spam(1, 2, 3) # Really calls the tracer wrapper object
spam('a', 'b', 'c') # Invokes _ _call_ _ in class
spam(4, 5, 6) # _ _call_ _ adds logic and runs original object
Also wenn ich die function mit den vorangestellten Deco-dinger aufrufe wird in dem obigen fall ne instance von tracer erstellt. Kann mich natürlich irren, wie gesagt: hab gerade erst angefange.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Das was du dort hast ist halt eine mögliche Ausprägung eines Decorators. Solange dieser etwas liefert, was "callable" ist, kannst du es auch aufrufen.

Als Decorator ist aber auch eine einfache Funktion denkbar. Folgender Decorator tut zum Beispiel gar nichts:

Code: Alles auswählen

def foo(x):
    return x

class Spam(object):
    @foo
    def bar(self):
        print "test"

Oder man setzt das erste Attribut der Methode:

Code: Alles auswählen

def foo(x):
    def p(*args, **kwds):
        x(42, *args, **kwds)
    return p

class Spam(object):
    @foo
    def bar(self, num):
        print num
cullmann
User
Beiträge: 13
Registriert: Donnerstag 10. April 2008, 19:08
Wohnort: Dublin

Ok, aber das functioner ja nur da die function callable ist und dies ist sie ja glaube ich nur da sie ein object als rückgabe wert liefert.
Würde foo "nur" einen int als rückgabewert liefern würde das wohl nicht funktionieren?

Aber erstmal besten dank für die nachhilfestunden um die uhrzeit.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Richtig. Würde "foo" einen Integer liefern, dann könntest du "bar" nicht mehr aufrufen, da der Name dann mit dem Integer verknüpft ist.
cullmann
User
Beiträge: 13
Registriert: Donnerstag 10. April 2008, 19:08
Wohnort: Dublin

Ok, schätze ich habs jetzt halbwegs verstanden, gut nächtle und nochmal danke.
Antworten