Klassen-Constructor

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
matthias11
User
Beiträge: 1
Registriert: Donnerstag 2. September 2010, 16:31

Ich verstehe nicht warum bei folgendem code list[1].vari eine Kopie von list[0].vari zu sein scheint?! IMO sollte list[1].vari als [] initialisiert sein.

Bitte um Hilfe/Erklärung

Code: Alles auswählen

>>> class Klasse:
...      def __init__(self, vari = []):
...             self.vari = vari
...
>>> list = []
>>> list.append(Klasse())
>>> list[0].vari
[]
>>> list[0].vari.append("eins")
>>> list[0].vari.append("zwei")
>>> list.append(Klasse())
>>> list[0]
<__main__.Klasse instance at 0xb778fe4c>
>>> list[1]
<__main__.Klasse instance at 0xb778feac>
>>> list[0].vari
['eins', 'zwei']
>>> list[1].vari
['eins', 'zwei']
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Das hat damit zu tun, dass die defaultwerte von Funktionen (und daher auch der Methoden) nur einmal ausgewertet werden und man immer dasselbe Objekt übergeben bekommt. Listen sind mutable und daher arbeitest du immer auf der gleichen Liste.

Besser:

Code: Alles auswählen

def foo(default=None):
    default = default or [] #oder was ähnliches
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
BlackJack

@matthias11: Das hat nichts mit Klassen zu tun, sondern wann Defaultargumente von Funktionen ausgewertet. Das passiert *einmal* wenn die ``def``-Anweisung ausgeführt wird. Das Ergebnis davon merkt sich das Funktionsobjekt und bei jedem Aufruf wird das gemerkte Objekt an den Namen gebunden (wenn kein Argument dafür übergeben wurde). Darum hast Du da nur eine Liste die bei jedem Exemplar der Klasse und bei jedem Aufruf der Funktion das selbe Objekt ist.

Darum sind veränderbare Objekte als Defaultargumente keine gute Idee. Es sei denn man will das Verhalten ausnutzen.

Üblicherweise belegt man solche Defaultargumente mit `None` und testet das in der Funktion.
Antworten