neue Instanz hat bereits Werte einer früheren Instanz

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
ZSchneidi
User
Beiträge: 9
Registriert: Montag 25. Juni 2012, 12:21

Hi Leute bin neu hier,

genauso neu auch in der Python community.
Beim titel is mir nur Mist eingefallen deswegen sorry dafür.
Fang gerade an das zu lernen und habe jetzt ein Problem, dass ich mir nicht erklären kann.

Folgende Grundlage habe ich:

Code: Alles auswählen

liste = []

class Example():
    
    name = ""
    
    example_list = []
    
    def __init__(self):
        self.name = ""
        #self.example_list = []

for i in range(2):
    print 'durchlauf '+str(i)
    temp_exa        = Example()
    temp_exa.name = 'name_'+str(i)
    
    print temp_exa.name
    if i == 0:
        temp_exa.example_list.append('foo '+str(temp_exa.name))
    else:
        temp_exa.example_list.append('bar '+str(temp_exa.name))
        
    
    print temp_exa.example_list
    liste.append(temp_exa)

for exa in liste:
    print exa
    print exa.example_list

Die erzeugte Ausgabe ist dann folgende:

Code: Alles auswählen

durchlauf 0
name_0
['foo name_0']
durchlauf 1
name_1
['foo name_0', 'bar name_1']
<__main__.Example instance at 0xb72b29cc>
['foo name_0', 'bar name_1']
<__main__.Example instance at 0xb6e3376c>
['foo name_0', 'bar name_1']
Ich hab mal versucht das stark zu vereinfachen.
Ich erzeuge mir also zwei Instanzen der Example Klasse und fülle diese. Unter anderem auch eine Liste.

Beim zweiten durchlauf enthällt die Liste Example.example_list bereits den wert, der der ersten Instanz zugewiesen wurde.
Hier hört es für mich dann auf, da komm ich mit meinen begrenzen Kenntnissen nicht mehr mit.

Wenn ich das hier auskommentierte self.example_list = [] in der __init__() funktion wieder rein nehme klappt es, das heißt jede
Instanz hat auch nur die ihr zugeordneten werte in der liste.

Da bräuchte ich unbedingt mal nen Ratschlag von euch.
Falls etwas unverständlich erklärt sein sollte versuche ich es gern noch genauer.

Danke
Zuletzt geändert von Anonymous am Montag 25. Juni 2012, 13:06, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Du definierst Klassenvariablen die für jede Instanz gültig sind. Bei name fällt es nicht auf, da der neue Wert durch die Zuweisung auch explizit neu an die Instanz gebunden wird.

Code: Alles auswählen

>>> class Person(object):
	name = 'unknown'
>>> bdfl = Person()
>>> bdfl.name = 'Guido'
>>> print bdfl.name
Guido
>>> print Person.name
unknown
>>> id(bdfl.name)
45134432
>>> id(Person.name)
36014976
Die Liste example_list selber hingegen ändert sich nicht, nur die Inhalte der Liste ändern sich. Korrekt wäre Folgendes um unabhängige Listen für jede Instanz aufzubauen.

Code: Alles auswählen

class Example(object):
    def __init__(self):
        self.name = ""
        self.example_list = []
Das Erben von object kannst du weglassen wenn du mit Python 3.x arbeitest.
ZSchneidi
User
Beiträge: 9
Registriert: Montag 25. Juni 2012, 12:21

Ok verstehe ich das richtig, dass member die nicht in der __init__ funktion definiert werden generell als static gehandhabt werden ?

Das würde auch das verhalten erklären.
Seltsam auch, dass python nicht gemeckert hat, dass ich nicht explizit von Objekt geerbt hab.
BlackJack

@ZSchneidi: Naja statisch sind die auch nicht, so etwas gibt es in Python nicht. Die sind dynamisch, aber halt auf der Klasse und nicht den Exemplaren, die aus dieser Klasse erstellt werden. Das gleiche gilt für die Methoden ja auch — die werden ja auf der gleichen Einrückungsebene definiert. Auf der Ebene definierst Du Attribute auf dem Klassenobjekt. Wenn Du bei einem Exemplar auf ein Attribut zugreifst, wird erst geschaut ob es das Attribut auf dem Exemplar gibt, und falls nicht wird in der Klassenhierarchie nach oben weiter gesucht.

Man muss in Python 2.x nicht von `object` erben, man sollte es aber immer tun. Denn nur wenn man das tut bekommt man eine „new style class”. Mit den „alten” kann man nicht alles tun was man mit den neuen kann. Ich denke da braucht man nicht weiter ins Detail gehen — merk Dir einfach: immer von Objekt erben, dann funktioniert alles wie in der Dokumentation beschrieben. :-)

Hier ist die erste Schleife etwas kompakter und „pythonischer” geschrieben:

Code: Alles auswählen

liste = list()
for i, text in enumerate(['foo', 'bar']):
    print 'Durchlauf', i
    example = Example()
    example.name = 'name_' + str(i)
    print example.name
    example.example_list.append('%s %s' % (text, example.name))
    print example.example_list
    liste.append(example)
ZSchneidi
User
Beiträge: 9
Registriert: Montag 25. Juni 2012, 12:21

Ok vielen Dank erst mal für die Hilfe,

ging wirklich schnell und kompetent.
Bin leider etwas unter druck und hab nicht viel Zeit groß Dokumentation zu lesen. *duck* :wink:

Aber danke für des nette Beispiel, ich werds noch lernen.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

ZSchneidi hat geschrieben:Bin leider etwas unter druck und hab nicht viel Zeit groß Dokumentation zu lesen. *duck* :wink:
Die Zeit, welche du jetzt durch das Nichtlesen der Dokumentation sparst, wirst du dir früher oder später so oder so mehrfach als zusätzlichen Aufwand wieder einhandeln ;-)
Das Leben ist wie ein Tennisball.
ZSchneidi
User
Beiträge: 9
Registriert: Montag 25. Juni 2012, 12:21

Geb ich dir vollkommen recht, aber die Deadline lässt das wirklich nicht zu und bis auf solche details klappt die Zusammenarbeit zwischen mir und Python doch ganz gut.
Antworten