Seite 1 von 1

Listen als Attribut eine Klasse

Verfasst: Montag 29. September 2008, 16:07
von alfonsospringer
Hi zusammen!

Wenn ich eine Klasse erstelle kann ich ja im Konstruktor ihre Attribute festlegen. Nun möchte ich als eines dieser Attribute eine Liste haben. Der Inhalt der Liste ist mir zu diesem Zeitpunkt jedoch noch nicht bekannt. Wie vermittle ich dann Python, was für einen Inhalt die Liste später umfassen wird? Oder denke ich da zu statisch (längere Zeit c++ programmiert) ?

Code: Alles auswählen

class test:
    def __init__(self):
        liste[] = ??? #Die Liste soll später zb Ints beinhalten. Wie definiere ich denn nun die Liste? 
    def __del__(self):
        pass

Versteht ihr, was ich meine? Vielen dank schonmal


/edit: habs.

Code: Alles auswählen

liste = []
definiert eine leere Liste.

Verfasst: Montag 29. September 2008, 16:11
von meneliel
eine leere Liste, die du später befüllst, legst du an mit

Code: Alles auswählen

mylist = list()
# oder
mylist2 = []
EDIT: Sorry, hab dein Edit zu spät gesehen ^^

Verfasst: Montag 29. September 2008, 16:22
von alfonsospringer
NP, vielen Dank

Verfasst: Montag 29. September 2008, 16:33
von BlackJack
@alfonsospringer: Vergiss bitte das es `__del__()` gibt. Das ist nicht wirklich zu gebrauchen weil nicht garantiert wird, wann die Methode aufgerufen wird, oder ob das *überhaupt* jemals passiert. Das reine Vorhandensein der Methode verhindert unter Umständen sogar, dass Objekte aus dem Speicher entfernt werden können.

Verfasst: Montag 29. September 2008, 16:41
von cofi
Kleines Detail am Rande: Dein Attribut `liste' - auch wenn die Syntax nicht stimmt - ist ein Klassenattribut.
Falls du ein Instanzattribut brauchst musst du `self.liste = []' nehmen. Das wird allerdings nicht so recht deutlich was du brauchst ;)

Zu `__del__': Das kannst du getrost weg lassen, denn der GC kümmert sich um die Entsorgung, ausserdem verleitet es dazu Logik reinzupacken und das sollte man in Python gar nicht tun ;)

Verfasst: Montag 29. September 2008, 17:28
von alfonsospringer
Magst du mir noch bitte den Unterschied zwischen Instanzattribut und Klassenattribut nennen?

Verfasst: Montag 29. September 2008, 17:43
von Darii
Ein Klassenattribut ist ein Attribut des Klassenobjekts, ein Instanzattribut ist ein Attribut der Instanz.

Code: Alles auswählen

In [120]: class Foo(object):
   .....:     bar = []
   .....:     
   .....:     def __init__(self):
   .....:         self.mybar = []
   .....:     
   .....:     def append(self, obj):
   .....:         self.bar.append(obj)
   .....:         self.mybar.append(obj)
   .....: 

In [121]: foo1 = Foo()

In [122]: foo2 = Foo()

In [123]: foo1.append("A")

In [124]: foo2.append("B")

In [125]: print foo1.bar
['A', 'B']

In [126]: print Foo.bar
['A', 'B']

In [127]: print foo1.mybar
['A']
bar ist hierbei das Klassenattribut und mybar das Instanzattribut.

Verfasst: Dienstag 30. September 2008, 10:42
von meneliel
BlackJack hat geschrieben:@alfonsospringer: Vergiss bitte das es `__del__()` gibt. Das ist nicht wirklich zu gebrauchen weil nicht garantiert wird, wann die Methode aufgerufen wird, oder ob das *überhaupt* jemals passiert. Das reine Vorhandensein der Methode verhindert unter Umständen sogar, dass Objekte aus dem Speicher entfernt werden können.

oha ... danke. Ich dachte das sei nötig, und hab daher z.B. in eine Klasse die ich für Datenbankverbindungen geschrieben hab (baut z.B. Verbindung zu Oracle auf, und managed Abfragen, Updates, .... ) extra ein __del__ eingebaut, damit auf jedenfall die Verbindung zur Datenbank geschlossen wird:

Code: Alles auswählen

def __del__(self):
        self.db.close()
.. ist demnach gar nicht gut und nicht zu gebrauchen?

Verfasst: Dienstag 30. September 2008, 11:16
von lunar
__del__ sollte nie benutzt werden, um Ressourcen zu bereinigen. Dafür gibt man der Klasse eine explizite close()-Methode (oder disconnect(), oder was auch immer passend ist). Zudem bietet sich an, in einer solchen Klasse das Kontextmanager-Protokoll zu implementieren, damit die Klasse in einer "with"-Statement verwendet werden kann.

Verfasst: Dienstag 30. September 2008, 12:16
von meneliel
zu was ist __del__ dann überhaupt gut?

Verfasst: Dienstag 30. September 2008, 13:22
von alfonsospringer
Juhu, ich kann auch mal eine Frage beantworten!

bei __del__(self): handelt es sich um den Destruktor einer Klasse. Diese funktion wird ausgeführt, wenn die Instanz einer Klasse stirbt. Ein kleines Beispiel:

Code: Alles auswählen

class testklasse():
   def __init__(self):
        print "Ich wurde grade erschaffen"
   def __del__(self):
        print "Ich bin grade gestorben"

a = testklasse()
del a
Mit a = test() erstellst du eine neue Instanz der Klasse testklasse. Dadurch wird der Konstruktor ( __init__(self): ) ausgeführt. Der erste Text wird folglich ausgegeben. Durch del a wird die Instanz wieder gelöscht, was bewirkt, dass der Destruktor ( __del__(self): ) ausgeführt wird. Der zweite Text wird folglich ausgegeben.

Hoffe damit ist deine Frage beantwortet

Verfasst: Dienstag 30. September 2008, 13:26
von meneliel
alfonsospringer hat geschrieben: Hoffe damit ist deine Frage beantwortet
^^ nee. Genau DESWEGEN hab ich __del__ ja verwendet und dort Code reingepackt, der ausgeführt werden soll, wenn die Klasse "stribt". Wird somit ja auch ausgeführt, wenn aus irgendeinem Grund mein Script abstürzt oder was weiß ich. ... erzählte mir zumindest ein Java-Entwickler

Verfasst: Dienstag 30. September 2008, 13:26
von name
alfonsospringer hat geschrieben:Juhu, ich kann auch mal eine Frage beantworten!

bei __del__(self): handelt es sich um den Destruktor einer Klasse. Diese funktion wird ausgeführt, wenn die Instanz einer Klasse stirbt. Ein kleines Beispiel
Schoen waers, ob der ausgefuehrt wird wenns garbage-collected wird ist afaik nicht sicher.

Verfasst: Dienstag 30. September 2008, 13:42
von lunar
meneliel hat geschrieben:
alfonsospringer hat geschrieben: Hoffe damit ist deine Frage beantwortet
^^ nee. Genau DESWEGEN hab ich __del__ ja verwendet und dort Code reingepackt, der ausgeführt werden soll, wenn die Klasse "stribt". Wird somit ja auch ausgeführt, wenn aus irgendeinem Grund mein Script abstürzt oder was weiß ich. ... erzählte mir zumindest ein Java-Entwickler
Und wie kommst du darauf, dass eine für Java gültige Aussage automatisch auch für Python Gültigkeit hätte? Auch in Java ist es schlecht, zum Bereinigen von Ressourcen finalize() zu nutzen. Im Gegenteil, Java-Objekte, die Ressourcen repräsentieren, haben alle eine dispose() oder close() Methode.

Auch in Java sollte eine Klasse niemals Logik im Destruktor ausführen. Der Java-GC ist da sogar noch schlechter geeignet als der Python-GC. Ersterer arbeitet überhaupt nicht deterministisch, es kann durchaus vorkommen, dass der gc während der Laufzeit eines Programms niemals abläuft. CPythons GC dagegen ist noch relativ deterministisch, weil er Objekte sofort abräumt, wenn der Refcount 0 erreicht. Wobei das natürlich ein Implementierungsdetail von CPython darstellt und weder IronPython noch iin Jython der Fall ist.
Ich bin mir nicht mal sicher, dass die JVM den Aufruf von finalize() garantiert.

@name
Die Doku sagt nur: "It is not guaranteed that __del__() methods are called for objects that still exist when the interpreter exits. " Ich interpretiere das so, dass der Aufruf von __del__ garantiert wird, wenn ein Objekt während der Laufzeit gelöscht wird. Allerdings ist der Aufruf von __del__ trotzdem weiter nicht deterministisch, so dass sowohl Zeitpunkt als auch Umstände des Aufrufs nicht vorhersehbar sind.