Forward Declarations
Das Problem gibt es in Python nicht. Alle Namen werden zur Laufzeit aufgelöst. Es gibt keine Deklarationen, ausser ``global`` aber das ist eine andere Baustelle.
Das funktioniert ohne Probleme weil `ham` erst aufgelöst wird, wenn `spam()` tatsächlich ausgeführt wird.
Code: Alles auswählen
def spam():
return ham()
def ham():
return 42
Code: Alles auswählen
def spam():
return ham()
print spam()
def ham():
return 42
- birkenfeld
- Python-Forum Veteran
- Beiträge: 1603
- Registriert: Montag 20. März 2006, 15:29
- Wohnort: Die aufstrebende Universitätsstadt bei München
Nein.
Nein. Falls das jemand erwarten würde, dann liegt das vielleicht daran, dass er ``def`` fälschlicherweise als Deklaration ansieht. ``def`` ist aber eine ausführbare Anweisung wie ``print``. Hier wird nach dem kompilieren erst das ``def spam():`` ausgeführt und dann das ``print spam()``. Zu dem Zeitpunkt wurde noch nichts ausgeführt, was den Namen `ham` an ein aufrufbares Objekt bindet, darum gibt's einen `NameError`.CrackPod hat geschrieben:Das würde dann aber nicht gehen, oder?Code: Alles auswählen
def spam(): return ham() print spam() def ham(): return 42
- birkenfeld
- Python-Forum Veteran
- Beiträge: 1603
- Registriert: Montag 20. März 2006, 15:29
- Wohnort: Die aufstrebende Universitätsstadt bei München
Das ist aber auch keine bessere Lösung. Nicht jedes Problem braucht eine Klasse (gottseidank)!Mad-Marty hat geschrieben:Nimm klassen, da gibts das problem garnicht erst.
Zuletzt geändert von birkenfeld am Sonntag 6. August 2006, 22:46, insgesamt 1-mal geändert.
- Michael Schneider
- User
- Beiträge: 569
- Registriert: Samstag 8. April 2006, 12:31
- Wohnort: Brandenburg
Hallo,
bei Klassen kann man auf alle im Körper der Klasse definierten Funktionsnamen unter Verwendung der automatisch übergebenen eigenen Objektreferenz zugreifen.
Eventuell ist das aber nicht der Kern der eigentlichen Frage. Vielleicht möchte gorba die Funktion als Argument übergeben und den Funktionscode später erst definieren.
Wenn das der Fall ist, sehe ich spontan zwei Möglichkeiten. Die schwierige ist, den neuen Code mit dem builtin Befehl "compile" zu erzeugen und dann dem Funktionsattribut func_code zuzuweisen. Ganz firm bin ich darin aber nicht und würde das mit Vorsicht genießen.
Die zweite einfache Variante ist wie immer ein Workaround: man definiert eine Funktion, die ein Element eines globalen Objektes ruft.
Ich hoffe das erklärt sich von selbst.
Grüße,
der Michel
bei Klassen kann man auf alle im Körper der Klasse definierten Funktionsnamen unter Verwendung der automatisch übergebenen eigenen Objektreferenz zugreifen.
Code: Alles auswählen
class dummy:
def spam(self):
return self.ham()
def ausgabe(self):
print self.spam()
def ham(self):
return 42
dummy().ausgabe()
Wenn das der Fall ist, sehe ich spontan zwei Möglichkeiten. Die schwierige ist, den neuen Code mit dem builtin Befehl "compile" zu erzeugen und dann dem Funktionsattribut func_code zuzuweisen. Ganz firm bin ich darin aber nicht und würde das mit Vorsicht genießen.
Die zweite einfache Variante ist wie immer ein Workaround: man definiert eine Funktion, die ein Element eines globalen Objektes ruft.
Code: Alles auswählen
def dummy(s): print "Guter", s ## erste Deklaration
dFunktionen = { "ausgabe": dummy } ## in globales Objekt aufnehmen
def ausgabe(s): dFunktionen["ausgabe"](s) ## aktuell referenzierte Funktion ausfuehren
ausgabe("Bulle") ## Testausgabe
def dummy(s): print "Boeser", s ## Neudeklaration
dFunktionen["ausgabe"] = dummy ## uebergabe an globales Objekt
ausgabe("Bulle") ## gleiches Argument an gleiche Funktion, aber ohoo...
Grüße,
der Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
- Michael Schneider
- User
- Beiträge: 569
- Registriert: Samstag 8. April 2006, 12:31
- Wohnort: Brandenburg
Moinmoin,
die letzte Erklärung mit dem Dictionary wirkt etwas grobschlächtig, wenn es nur um eine Funktion geht, hat aber Vorteile, wenn mehrere zusammengefasst werden können. Es ist übrigens nicht notwendig, die Funktion vorher zu definieren, wie man in der folgenden Gegenüberstellung sehen kann.
Dieser direkte Vergleich zeigt, dass man nicht den Funktionsnamen der Zielfunktion übergeben darf, sondern eine Wrapper-Funktion schaffen muss, die auf die globale Variable verweist. In diesem Zusammenhang hüte man sich vor einer Deklaration wie
in Zeile 11. Denn durch f=f wird eine neue Variable im lokalen Namensraum geschaffen und der Bezug geht, wie in der oberen Variante, verloren. Solange man "f" in "ausgabe" nicht überschreibt, verweist es auf den globalen Namensraum.
Grüße,
der Michel
die letzte Erklärung mit dem Dictionary wirkt etwas grobschlächtig, wenn es nur um eine Funktion geht, hat aber Vorteile, wenn mehrere zusammengefasst werden können. Es ist übrigens nicht notwendig, die Funktion vorher zu definieren, wie man in der folgenden Gegenüberstellung sehen kann.
Code: Alles auswählen
#######################
## funktioniert nicht!
def ausgabe(a): print "denkste" ## Funktion mit Code definieren
funk = ausgabe ## Namen an Callback-Variable geben
def ausgabe(a): print a ## Funktionscode aendern
funk("Hallo Welt!") ## welche Funktion wird ausgefuehrt?
#######################
## so geht es
f = None ## Funktionsnamen initialisieren
def ausgabe(a): f(a) ## Wrapperfunktion ruft Funktion (Argumente!)
funk = ausgabe ## Namen an Callback-Variable geben
def f(a): print a ## Funktion ausformulieren
funk("Hallo Welt!") ## jetzt wird die aktualisierte Funkt. gerufen
Code: Alles auswählen
def ausgabe(a, f=f)
Grüße,
der Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Und welches "Problem" löst das jetzt genau? Ohne die Klasse, mit den Methoden als Funktionen auf Modulebene funktioniert's genau so, nur das man sich die überflüssige Klasse spart:Michael Schneider hat geschrieben:bei Klassen kann man auf alle im Körper der Klasse definierten Funktionsnamen unter Verwendung der automatisch übergebenen eigenen Objektreferenz zugreifen.
Code: Alles auswählen
class dummy: def spam(self): return self.ham() def ausgabe(self): print self.spam() def ham(self): return 42 dummy().ausgabe()
Code: Alles auswählen
def spam():
return ham()
def ausgabe():
print spam()
def ham():
return 42
ausgabe()
Code: Alles auswählen
class A:
load = staticmethod(load)
def load(self, filename):
pass
a = A()
- Michael Schneider
- User
- Beiträge: 569
- Registriert: Samstag 8. April 2006, 12:31
- Wohnort: Brandenburg
Hi BlackJack,
Du hast recht, aber auch wenn das auf Modulebene geht, widerspricht es nicht meiner Aussage:
Grüße,
Michael
Du hast recht, aber auch wenn das auf Modulebene geht, widerspricht es nicht meiner Aussage:
Das jedoch schon :Michael Schneider hat geschrieben: bei Klassen kann man auf alle im Körper der Klasse definierten Funktionsnamen unter Verwendung der automatisch übergebenen eigenen Objektreferenz zugreifen.
In diesem Fall bringt die Klasse keinen Vorteil und ich würde die Funktionen auch vorziehen. Aber in vielen (komplexeren) Fällen ist die strukturelle Kapselung in Klassen eben übersichtlicher. Muss man von Fall zu Fall entscheiden.BlackJack hat geschrieben:Code: Alles auswählen
class A: load = staticmethod(load) def load(self, filename): pass a = A()
Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...