Optionale Objektattribute und Klassenattribute

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
Zinober
User
Beiträge: 20
Registriert: Freitag 26. Dezember 2014, 15:58

Hallo,

ich bin gerade auf ein Verhalten von Python beim Umgang mit den optionalen Attributen von Objekten gestoßen, dass mich sehr überrascht hat. Ich habe eine eigene Klasse mit mehreren optionalen Argumenten, von denen einige Listen sind. Wird das Argument beim Instantiieren nicht angegeben, sollten diese Listen eigentlich leer sein. Stattdessen scheint so was wie ein Klassenattribut zu entstehen.
Ich würde mich sehr freuen, wenn mir jemand helfen könnte, das zu verstehen, und natürlich auch darüber, wenn jemand einen Tipp hätte, wie ich das gewünschte Verhalten erreiche.

Viele Grüße
Thorsten

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

class Klasse:
    def __init__(self,name,liste=[]):
        self.name = name
        self.liste = liste
        
instanz = Klasse('erste')
instanz.liste.append('element')
print(instanz.name,instanz.liste[0])

instanz = Klasse('zweite')
print(instanz.name,instanz.liste[0])

instanz_ = Klasse('dritte')
print(instanz_.name,instanz_.liste[0])

instanz_.liste.append('weiteres element')
print(instanz.name,instanz.liste[1])
Ausgabe:

Code: Alles auswählen

erste element

zweite element

dritte element

zweite weiteres element
Sirius3
User
Beiträge: 18276
Registriert: Sonntag 21. Oktober 2012, 17:20

Du erzeugst eine Liste, und diese eine Liste ist das default-Argument. Es wäre verwunderlich, wenn das Verhalten anders wäre und plötzlich Objekte erzeugt werden, ohne dass das explizit dastehen würde.
Wenn Du eine Liste pro Instanz willst, mußt Du das auch programmieren, also "wenn keine Liste übergeben wurde, erstelle eine neue":

Code: Alles auswählen

class Klasse:
    def __init__(self, name, liste=None):
        self.name = name
        self.liste = [] if liste is None else liste
Zinober
User
Beiträge: 20
Registriert: Freitag 26. Dezember 2014, 15:58

Hallo Sirius3,

vielen Dank für deine Antwort!
Deine Lösung funktioniert und hilft mir ein großes Stück weiter.

Über die Erklärung muss ich nochmal meditieren...
Ich bin zum einen davon ausgegangen, dass [] immer für eine leere Liste steht, so wie in

Code: Alles auswählen

>>> liste = []
>>> liste.append('element')
>>> liste = []
>>> print(len(liste))
0
zum anderen dachte ich, dass die Attribute, die in __init__ mit self eingeführt werden, wirklich Instanzattribute sind, die auch nur über das Objekt angesprochen werden können.
... nun ja, offensichtlich habe ich mich geirrt. ;-)

Vielen Dank und viele Grüße
Thorsten
Benutzeravatar
kbr
User
Beiträge: 1508
Registriert: Mittwoch 15. Oktober 2008, 09:27

Du bist über den Fallstrick "mutable Datentypen als Defaultwerte" gestolpert. Diese werden beim Laden des Moduls nur einmal angelegt. Jede Instanz Deiner Klasse hat anschließend mit `self.liste` eine Referenz auf dieses eine Objekt, sofern nichts anderes explizit übergeben wird.
Antworten