Listen verarbeiten

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
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Hallo zusammen,

ich habe eine Reihe mit Daten in einer Liste und muss diese Liste verarbeiten. Konkret ist angedacht die Liste in einer Klasse als Attribut vorzuhalten und dann je nach Bedarf umzurechnen, aber auch bestimmte Werte rauszuschmeißen und das Ergebnis in einem anderen Attribut zu speichern.

Code: Alles auswählen

liste = [1,2,3]
liste2 = liste

liste2.pop()

print("Liste und Magie")
print(liste)
print(liste2)

"""
# Ergibt:
Liste und Magie
[1, 2]
[1, 2]
"""

def liste_drehen(liste):
    return liste[::-1]

liste = [1,2,3]
liste2 = liste

liste = liste_drehen(liste)

print("Liste und Funktion")
print(liste)
print(liste2)

"""
# Ergibt:
Liste und Funktion
[3, 2, 1]
[1, 2, 3]
"""

class ListenKlasse(object):
    
    raw_liste = []
    liste_neu = []

    def __init__(self, liste):

        self.raw_liste = liste
        self.liste_neu = self.raw_liste[::-1]

liste = [1,2,3]
liste2 = liste

lk = ListenKlasse(liste)

print("Liste und Klasse")
print(liste)
print(liste2)
print(lk.raw_liste)
print(lk.liste_neu)

"""
# Ergibt:
Liste und Klasse
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
[3, 2, 1]

"""
Ich habe in Erinnerung, dass Listen sich seltsam verhalten können. Ich habe mal obiges versucht, um Überraschungen zu minimieren. Wenn ich es richtig sehe, dann machen mir Listen, die ich in Funktionen verarbeite und Listen, die ich mittels Klassen verarbeite, keine Schwierigkeiten. Hintergrund ist, dass ich die Rohdaten in der Klasse speichern muss und verfügbar halten möchte. Wenn mir da - unerkannt - Änderungen unterlaufen, wäre das nicht überragend. Gibt es Überraschungspotenzial, das ich nicht im Blick habe? Kleiner Hinweis wäre freundlich.
Zuletzt geändert von Anonymous am Dienstag 24. November 2015, 21:38, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@pixewakb: bei Listen ist nichts magisches, wenn man weiß, dass Variablennamen nur Verweise auf die Objekte sind. Ein Slice-Zugriff auf eine Liste liefert eine neue Liste mit den entsprechenden Elementen. Daher ist der Rückgabewert Deiner liste_drehen-Liste unabhängig von ihrem Argument.

Klassenattribute sind nicht dazu da, Instanzattribute zu definieren!
BlackJack

@pixewakb: Du musst im Grunde nur zwei Sachen wissen: a) Eine Zuweisung kopiert nichts, da hat das *selbe* Objekt am Ende einfach nur einen anderen zusätzlichen Namen und b) welche Operationen ein Objekt verändern und welche nicht. `pop()` verändert die Liste, [::-1] nicht. Das hat nichts mit Magie zu tun, und da machen auch Funktionen oder Klassen keinerlei Unterschied. Wenn Du in der Funktion `pop()` aufgerufen hättest, dann wäre die Ausgabe in Zeile 13 und 14 die Folge gewesen.

Die Zeilen 38 und 39 sind falsch und gefährlich. Du willst an der Stelle keine Klassenattribute haben!

Und auch hier wieder: Wenn Du in der `__init__()` die `pop()`-Methode aufgerufen hättest…
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Ich verstehe folgende 2 Sätze nicht:

(1) Was ist der Unterschied zwischen Klassen- und Instanzattributen?
Klassenattribute sind nicht dazu da, Instanzattribute zu definieren!
(2) Mir erschließt sich der Unterschied nicht und d. h. ich sehe wahrscheinlich auch die Konsequenzen nicht.
Die Zeilen 38 und 39 sind falsch und gefährlich. Du willst an der Stelle keine Klassenattribute haben!
Ich hatte es einmal erlebt, dass ich eine Klasse in einer Schleife erzeugt habe und die Objekte nicht sauber waren, sondern noch Daten vom vorletzten Durchlauf mitschleppten. Zeilen wie 38 und 39 hatten das behoben. Wo ist der Unterschied, ob ich die dort definiere oder nur in der init-Methode?

PS Ich gewinne den Eindruck, dass ich da etwas mit OO noch nicht verstanden habe.
BlackJack

@pixewakb: Klassenattribute sind auf der Klasse definiert und gelten für alle Exemplare und ”Instanz”attribute sind auf jedem Exemplar definiert und gelten nur dort. Was Du da mit ”sauber” beschreibst ist eher der umgekehrte Fall, eben weil Klassenattribute für alle Exemplare den gleichen Wert haben.

In Deinem Beispiel werden die überhaupt nicht benutzt, darum sind sie dort auch mindestens sinnlos.
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Das ich das verstehe:
Klassenattribute -- verwende ich dann z. B., wenn ich eine Konstante habe, die immer gilt, also z. B. 1 cm = 10 mm?
Instanzattribute -- verwende ich, um veränderliche Daten vorzuhalten? Also, jedenfalls definiere ich sie z. B. via __init__()-Methode?

Ich habe gerade mal geschaut und konnte zwischen Klassen- und Instanzattributen keinen für mich wahrnehmbaren Unterschied feststellen:

Code: Alles auswählen

class Test():
    w = 2
    def __init__(self, a):
        self.a = a

t = Test(1)

print(t.a)
print(t.w)
print(Test.w)
Liefert bei mir in der Konsole:

Code: Alles auswählen

>>> 
1
2
2
Bislang habe ich in meinen Programmen zwischen Klassen- und Instanzattributen wohl noch nicht sauber unterschieden. Worauf müsste ich im Kern achten? Geht es nur um Gewohnheiten oder gibt es ein technisches Problem, das ich noch nicht sehe.

In Sachen Listen: Ich muss die Rohdaten vorhalten, aber auch munter konvertieren. Gibt es eine saubere Lösung, dass ich die Listen in der Klasse vorhalte und verhindere, dass ich die Rohdaten ändere!? Also z. B. dann die Liste mittels methode(self, liste[:]) an die Methode übergebe oder gibt es ein besseres Verfahren?
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Hier mal ein Beispiel.

Code: Alles auswählen

class Foo:
    class_attribute = []

    def __init__(self):
        self.instance_attribute = []

x = Foo()
y = Foo()
x.instance_attribute.append(1)
y.instance_attribute.append(2)
x.class_attribute.append(3)
y.class_attribute.append(4)
x.instance_attribute ist [1] und y.instance_attribute ist [2] da es sich dabei um zwei unterschiedliche Listen handelt. Dahingegen sind x.class_attribute und y.class_atttribute identisch mit dem Wert [3, 4].
Antworten