Seite 1 von 1
Attribut als default-Parameter in Klassenmethode?
Verfasst: Dienstag 23. August 2005, 15:27
von N317V
Hi, zusammen!
Man kann ja in Python bei einer Funktions- bzw. Methodendefinition für einen Parameter einen default-Wert definieren. Aber
Code: Alles auswählen
class foo:
def __init__(self):
self.irgendwas = 'dingsbums'
def methodeEins(self, parameter=self.irgendwas):
sonstiger Code
bringt mir den Fehler "NameError: name 'self' is not defined". Irgendwer ne Idee, was da falsch ist oder wie man das lösen kann?
TIA
Greetings!
N317V
Verfasst: Dienstag 23. August 2005, 15:33
von jens
Vielleicht nicht ganz was du willst:
Code: Alles auswählen
class foo:
irgendwas = 'dingsbums'
def methodeEins(self, parameter=irgendwas):
print parameter
Verfasst: Dienstag 23. August 2005, 15:41
von N317V
Lösung hab ich jetzt doch noch schnell gefunden:
Code: Alles auswählen
def methodeEins(self, parameter=None):
if not parameter:
parameter=self.irgendwas
Nicht unbedingt der Bringer, aber immerhin gehts. Trotzdem versteh ich nicht so ganz, warum das andere nicht funktioniert. Das hielte ich für wesentlich eleganter.
Verfasst: Dienstag 23. August 2005, 15:44
von mawe
Hi!
Deine Methode etwas abgewandelt:
Code: Alles auswählen
In [1]: class Foo:
...: def __init__(self):
...: self.var = "blabla"
...: def methode(self, parameter=None):
...: bla = parameter or self.var
...: print bla
...:
In [2]: f = Foo()
In [3]: f.methode()
blabla
In [4]: f.methode("gaga")
gaga
Gruß, mawe
Verfasst: Dienstag 23. August 2005, 16:02
von N317V
Auf jeden Fall schon mal Danke Euch beiden für die superschnelle Hilfe. Hat noch jemand ne Erklärung dafür, warum self nicht definiert ist? Ist doch auch der erste Parameter.
Verfasst: Dienstag 23. August 2005, 18:45
von henning
Ich nehme mal an, dass die Parameter erst im Funktionsrumpf als definiert gelten, wenn die Parameterliste angearbeitet ist.
Die default-Parameter-Zuweisung ist ja aber innerhalb der Parameterliste, deshalb ist self zu dem Zeitpunkt noch nicht definiert.
Das muss auch so sein, denn wenn ich folgendes habe:
Code: Alles auswählen
def foo(a, b, c=a.lower()):
print a, b, c
d = {
"a": "HALLO",
"b": "blah",
"c": 34
}
foo(**d)
dann
kann dies nicht funktionieren, da ja nicht klar ist, in welcher Reihenfolge die keyowrd-werte aus dem dictionary geholt werden! (Elemente in einem Dictonary haben keine vorhersagbare Reihenfolge, zumindest konzeptionell)
PS: Man könnte eventuell einwenden, dass die keywords in Reihenfolge der Parameterliste raus geholt werden.
Fällt mir auch kein gutes Gegenargument zu ein, aber vielleicht veranschaulicht es das Dilemma trotzdem ein wenig.
Verfasst: Dienstag 23. August 2005, 22:08
von BlackJack
mawe hat geschrieben:Hi!
Deine Methode etwas abgewandelt:
Code: Alles auswählen
In [1]: class Foo:
...: def __init__(self):
...: self.var = "blabla"
...: def methode(self, parameter=None):
...: bla = parameter or self.var
...: print bla
Ich würde nach Möglichkeit immer mit ``if`` auf ``is not None`` prüfen wenn man sich nicht ganz sicher ist, das nie ein Wert übergeben werden können soll, der "falsch" ist. Da oben kann man `parameter` zum Beispiel nicht explizit auf eine leere Zeichenkette setzen. Oder bei numerischen Werten schliesst man die 0 aus usw.
Verfasst: Mittwoch 24. August 2005, 06:47
von jens
Ich würde es auf lieber mit
if machen, weil's einfacher zu verstehen ist... Die
or Variante ist mir zu abgefahren, auch wenns schön klein ist
Verfasst: Mittwoch 24. August 2005, 09:15
von N317V
Ich find die or-Variante voll geil; sehr pythonic
Und ich bin mir auch ganz sicher, dass da kein Wert übergeben werden soll, der False ergibt.
@henning: Dein Code-Beispiel leuchtet mir ein. Warum aber self an jede Methode der Klasse übergeben werden
muss, andererseits aber zu dem Zeitpunkt nicht definiert ist, ist mir schleierhaft. Zumal ich diese Art der Vorbelegung für am sinnvollsten halte.
Verfasst: Mittwoch 24. August 2005, 09:52
von Gast
Das mit dem self ist eigentlich ganz logisch, wenn man mal
kurz vergisst, dass die Funktionen zu einem Objekt gehören.
An und für sich sind Funktionen, die in einer Klasse definiert werden
ja erstmal Klassenvariablen die zufällig den Typ Funktion haben.
Die gibts aber nur einmal pro Klasse, daher wissen sie nichts von einer Instanz (also dem Objekt der Klasse)!
Deswegen
muss man self als Parameter entgegennehmen, damit man Zugriff auf das Objekt hat.
Wenn man folgendes hat:
Code: Alles auswählen
class Klasse:
def func(self, a, b):
self.blah = "foo"
k = Klasse()
Dann ist
Nur eine andere Schreibweise
(also wenn an so will "sntactic sugar") für
Verfasst: Mittwoch 24. August 2005, 09:54
von henning
Das letzte Posting ist von mir, war nicht eingeloggt.
Verfasst: Mittwoch 24. August 2005, 10:04
von N317V
@henning:
Heißt das, ich rufe eigentlich die Klasse auf, "starte" eine Funktion und übergebe ihr die Instanz und weitere Parameter? Puh! Ganz schön wirr.
Aber selbst wenn: wieso kann ich die Instanz übergeben, eine der Instanz bei deren Erzeugung zugewiesenes Attribut jedoch nicht. Das macht doch keinen Sinn.
Verfasst: Mittwoch 24. August 2005, 10:06
von jens
Anonymous hat geschrieben:Nur eine andere Schreibweise
(also wenn an so will "sntactic sugar") für
Das geht so allerdings nicht! So funktionierts:
Verfasst: Mittwoch 24. August 2005, 10:18
von henning
Also ich hatte mein Beispiel nicht getestet, aber was du schreibst wundert mich, weil Klasse() doch auch wieder ein Objekt ist, da müssten der Funktion insgesamt 4 Parameter übergeben werden, oder?!
N317V:
Nein, eigentlich ganz logisch, man ists nur nicht geöhnt von anderen OO-Sprachen ,-)
Ausserdem kannst du auch ein attribut der instanz übergeben:
Code: Alles auswählen
class Klasse:
def __init__(self):
self.x = 45
self.y = 36
def func(self, a, b):
return self.y + a + b;
k = Klasse()
k.func(k.x, 7)
self ist bloß innerhalb der Parameterliste der Funktion nicht definiert!
Verfasst: Mittwoch 24. August 2005, 10:32
von mawe
henning hat geschrieben:
aber was du schreibst wundert mich, weil Klasse() doch auch wieder ein Objekt ist, da müssten der Funktion insgesamt 4 Parameter übergeben werden, oder?!
Richtig, wie man auch an der Fehlermeldung sieht die man erhält
Klasse.func(k, 3, 4) stimmt schon.
Verfasst: Mittwoch 24. August 2005, 10:37
von jens
Halt. In eurem Fall wird bei
k.func(k.x, 7) die Klassenvariable 'x' mitgeschickt. Das geht natürlich nicht, wenn es
k nicht gibt
Schauen wir uns mal folgende Klasse an:
Code: Alles auswählen
class foo:
irgendwas = 'dingsbums'
def methodeEins(self, parameter=irgendwas):
print parameter
Hierbei geht der "direkte" Aufruf schon so:
foo().methodeEins("jo") aber nicht so:
foo.methodeEins("jo")
Verfasst: Mittwoch 24. August 2005, 10:44
von mawe
jens, bitte lies Dir noch mal den Beitrag von henning und Deine Antwort darauf durch. Dort ist nämlich mit
k = Klasse() längst eine Instanz erzeugt
Verfasst: Mittwoch 24. August 2005, 10:46
von jens
Ups
Jetzt verstehe ich erst wie das gemeint war