@Michael
Ich versteh das schon, nur wie oben gezeigt, lassen sich die Werte der einzelnen Instanzen ohne Einfluss aufeinander ändern.
LG
r_r
Klassenattributte umbn(__init__ aufruf...was ruft er da auf)
- Michael Schneider
- User
- Beiträge: 569
- Registriert: Samstag 8. April 2006, 12:31
- Wohnort: Brandenburg
Hallo Rolgal!
Wenn Du dem Namen innerhalb der Instanz ein neues Objekt zuweist, dann trennen sich genau da die Wege des Namens und Du greifst fortan von Klasse und Instanz auf unterschiedliche Objekte zu. Bis dahin referenzierten beide Namen (von Klasse und Instanz) dasselbe Objekt:
Wenn Du dem Namen aber kein neues Objekt zuweist, sondern dasselbe Objekt nur modifizierst (im folgenden Beispiel list.append), dann referenzierst Du weiterhin dasselbe Objekt mit demselben Namen:
Das kann erwünscht sein, aber auch nicht.
Grüße,
Michael
Ja, es geht darum, ob prinzipiell dasselbe Objekt an die Instanz weitergegeben wird, oder gleich eine Kopie - also ein anderes Objekt.rolgal_reloaded hat geschrieben:Die Werte können auch nur für eine Instanz geändert werden, wenn es Klassenattribute sind.
Oder überseh ich einen wesentlichen Unterschied:
Code: Alles auswählen
>>> class A: var1 = 5 var2 = 10
Wenn Du dem Namen innerhalb der Instanz ein neues Objekt zuweist, dann trennen sich genau da die Wege des Namens und Du greifst fortan von Klasse und Instanz auf unterschiedliche Objekte zu. Bis dahin referenzierten beide Namen (von Klasse und Instanz) dasselbe Objekt:
Code: Alles auswählen
>>> class A:
... var = 5
...
>>> a1, a2 = A(), A()
>>> a1.var, a2.var
(5, 5)
>>> A.var = 10
>>> a1.var, a2.var
(10, 10)
>>> a1.var = 15
>>> a1.var, a2.var
(15, 10)
Code: Alles auswählen
>>> class B:
... var = [5]
...
>>> b1, b2 = B(), B()
>>> b1.var, b2.var
([5], [5])
>>> B.var.append(10)
>>> b1.var, b2.var
([5, 10], [5, 10])
>>> b1.var.append(15)
>>> b1.var, b2.var
([5, 10, 15], [5, 10, 15])
Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
-
- User
- Beiträge: 312
- Registriert: Dienstag 24. Oktober 2006, 19:31
Alles klar, aber wäre es nicht doch besser, die Defaultwerte in __init__ reinzuschreiben. Entspricht das nicht mehr der Idee eines Konstruktors?
Also:
Code: Alles auswählen
class A:
def __init__(self, var1 = [], var2 = []): #usw.
self.var1 = var1
self.var2 = var2
LG
rolgal_reloaded
- Michael Schneider
- User
- Beiträge: 569
- Registriert: Samstag 8. April 2006, 12:31
- Wohnort: Brandenburg
Hi rolgal,rolgal_reloaded hat geschrieben:@Michael
Ich versteh das schon, nur wie oben gezeigt, lassen sich die Werte der einzelnen Instanzen ohne Einfluss aufeinander ändern.
LG
r_r
leider nicht. Es macht wirklich einen Unterschied, ob bei der Instanzierung einer Klasse eine Referenz auf das Objekt der Klasse übergeben wird, oder eine Kopie. In Deinem Beispiel hatte das Ändern des Integerwertes nur deshalb keinen Einfluss, weil Integerobjekte nicht veränderbar sind und Python nicht dem von der Klasse aus referenzierten Integerobjekt den Wert 5 gegeben hat, sondern statt dessen dem instanzlokalen Namen das (neue) Integerobjekt mit dem Wert 10 zugeordnet hat.
Wie oben gezeigt: bei veränderbaren Objekten geht das nicht - solange Du ihnen kein neues Objekt zuweist. Beachte, dass z.B. "list1 = list1 + [10]" zwar eine neue Liste liefert, diese aber nicht mehr das Objekt list1 ist:
Alle Klarheiten beseitigt?>>> l1 = [5]
>>> l1, id(l1)
([5], 13057200)
>>> l1.append(10)
>>> l1, id(l1)
([5, 10], 13057200)
>>> l1 = l1+[15]
>>> l1, id(l1)
([5, 10, 15], 13024032)
Grüße,
Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
- Michael Schneider
- User
- Beiträge: 569
- Registriert: Samstag 8. April 2006, 12:31
- Wohnort: Brandenburg
Es gibt eine Initialisierung der Klasse (i.d.R. beim Programmstart ausgeführt) und je eine Initialisierung pro Instanz. Was Du jetzt geschrieben hast, entspricht [EDIT: ebenfalls nicht (siehe BlackJacks Erklärung unten)] grandmas Vorschlag. Allein der Zweck entscheidet hier, wo man Namen initialisiert. Aber ich finde, Du hast Recht: Konstanten kann man im Namensraum der Klasse definieren.rolgal_reloaded hat geschrieben:
Alles klar, aber wäre es nicht doch besser, die Defaultwerte in __init__ reinzuschreiben. Entspricht das nicht mehr der Idee eines Konstruktors?
Also:
Code: Alles auswählen
class A: def __init__(self, var1 = [], var2 = []): #usw. self.var1 = var1 self.var2 = var2
Grüße,
Michael
Zuletzt geändert von Michael Schneider am Dienstag 19. Juni 2007, 12:39, insgesamt 1-mal geändert.
Diese Nachricht zersört sich in 5 Sekunden selbst ...
-
- User
- Beiträge: 312
- Registriert: Dienstag 24. Oktober 2006, 19:31
Danke für die Klarstellung, wieder was wichtiges konkretisiert im Oberstübchen,
liebe Grüße
rolgal_reloaded
liebe Grüße
rolgal_reloaded
Das ist nicht viel anders oder besser als Klassenattribute weil die Defaultwerte, genau wie Klassenattribute nur *einmal* ausgewertet werden, nämlich wenn das ``def __init__(...)`` ausgeführt wird:rolgal_reloaded hat geschrieben:Alles klar, aber wäre es nicht doch besser, die Defaultwerte in __init__ reinzuschreiben. Entspricht das nicht mehr der Idee eines Konstruktors?
Also:
Oder gibt es Fälle wo das wie vom Autor des Threads gezeigt wird besser ist?Code: Alles auswählen
class A: def __init__(self, var1 = [], var2 = []): #usw. self.var1 = var1 self.var2 = var2
Code: Alles auswählen
In [1]: class A(object):
...: def __init__(self, var1=[], var2=[]):
...: self.var1 = var1
...: self.var2 = var2
...:
In [2]: x = A()
In [3]: y = A()
In [4]: x.var1.append(42)
In [5]: x.var1
Out[5]: [42]
In [6]: y.var1
Out[6]: [42]
In [7]: x.var1 is y.var1
Out[7]: True
-
- User
- Beiträge: 312
- Registriert: Dienstag 24. Oktober 2006, 19:31
@BlackJack
Hast es wieder geschafft mich zu verwirren bzw. mir klar zu machen, dass mir da etwas ganz und gar nicht so klar ist.
Dass sich die Modifizierung von Klassenattributen auf alle Instanzen auswirken kann, wie von Michael gezeigt, erscheint mir logisch.
Aber warum denn in meinem Beispiel. Und warum passiert hier was anderes:
LG
rolgal_reloaded
Hast es wieder geschafft mich zu verwirren bzw. mir klar zu machen, dass mir da etwas ganz und gar nicht so klar ist.
Dass sich die Modifizierung von Klassenattributen auf alle Instanzen auswirken kann, wie von Michael gezeigt, erscheint mir logisch.
Aber warum denn in meinem Beispiel. Und warum passiert hier was anderes:
Code: Alles auswählen
>>> class A(object):
def __init__(self):
self.var1 = []
self.var2 = []
>>> x = A()
>>> y = A()
>>> x.var1.append(42)
>>> x.var1
[42]
>>> y.var1
[]
>>>
rolgal_reloaded
Die Erklärung habe ich eigentlich schon gegeben:
Der Ausdruck hinter dem '=' in der Funktionsdefinition wird ein einziges mal ausgewertet, nämlich dann wenn das ``def`` als Teil der Klassendefinition ausgeführt wird. Das Ergebnis dieses Ausdrucks wird bei jedem Aufruf der Methode an den Namen `var1` gebunden. Das ist immer die selbe Liste.
Der Körper der Funktion wird dagegen bei jedem Aufruf der Funktion abgearbeitet. Das heisst `self.var2` wird jedesmal an eine neue Liste gebunden.
Code: Alles auswählen
class A(object):
def __init__(self, var1=[]):
self.var1 = var1
self.var2 = []
Der Körper der Funktion wird dagegen bei jedem Aufruf der Funktion abgearbeitet. Das heisst `self.var2` wird jedesmal an eine neue Liste gebunden.
-
- User
- Beiträge: 312
- Registriert: Dienstag 24. Oktober 2006, 19:31
Naja, so wie oben eben nicht, sonst hätte ich (wir) nicht nachgefragtBlackJack hat geschrieben:Die Erklärung habe ich eigentlich schon gegeben:
Jetzt ist klar warum das so ist.
Aber ist das eigentlich gut, dass es so ist, oder sollte das nicht anders sein??
Oder anders gesagt: weiss ich jetzt endlich, warum ein Konstruktor wie am Anfang des Threads gezeigt sinnvoll sein kann.
LG
rolgal_reloaded
-
- User
- Beiträge: 312
- Registriert: Dienstag 24. Oktober 2006, 19:31
Also ich finde das immer noch schräg......
Wer noch, oder wer nicht? Und vor allem wenn nicht, W A R U M ???
Wer noch, oder wer nicht? Und vor allem wenn nicht, W A R U M ???
An der Stelle muss(te) man ein Entscheidung treffen: Werden Default-Werte einmal berechnet wenn die Funktion definiert wird, oder jedesmal wenn die Funktion aufgerufen wird.
Zwei Gründe für's einmalige berechnen:
a) Es muss nur einmal gemacht werden.
b) Berechnen bei jedem Funktionsaufruf kann man auch *in* der Funktion machen, wenn man das braucht.
In den allermeisten Fällen sind die Default-Werte in der Praxis nach meiner Erfahrung sowieso "immutables", da braucht man nur eine Auswertung.
Zwei Gründe für's einmalige berechnen:
a) Es muss nur einmal gemacht werden.
b) Berechnen bei jedem Funktionsaufruf kann man auch *in* der Funktion machen, wenn man das braucht.
In den allermeisten Fällen sind die Default-Werte in der Praxis nach meiner Erfahrung sowieso "immutables", da braucht man nur eine Auswertung.
-
- User
- Beiträge: 312
- Registriert: Dienstag 24. Oktober 2006, 19:31
@BlackJack
...was meinst du jetzt mit immutables? - Beispiel?
LG
rolgal_reloaded
...was meinst du jetzt mit immutables? - Beispiel?
LG
rolgal_reloaded
Blick zwar schon lange nicht mehr was hier so diskutiert wird
aber immutables kenne ich
So mal als Beispiel
aber immutables kenne ich
Code: Alles auswählen
# Immutables ( unveränderbar )
# Unter anderem keine in-place modifikation möglich
"..." # Strings
1 # int
1.2 # float
# Mutables ( veränderbare )
[] # lists
{} # dicts
-
- User
- Beiträge: 312
- Registriert: Dienstag 24. Oktober 2006, 19:31
Ach so,.....alles klar!Zap hat geschrieben:Blick zwar schon lange nicht mehr was hier so diskutiert wird
aber immutables kenne ich
So mal als BeispielCode: Alles auswählen
# Immutables ( unveränderbar ) # Unter anderem keine in-place modifikation möglich "..." # Strings 1 # int 1.2 # float # Mutables ( veränderbare ) [] # lists {} # dicts
Danke!
- Michael Schneider
- User
- Beiträge: 569
- Registriert: Samstag 8. April 2006, 12:31
- Wohnort: Brandenburg
Hi,rolgal_reloaded hat geschrieben:@BlackJack
...was meinst du jetzt mit immutables? - Beispiel?
auch wenn ich nicht gefragt wurde:
Unveränderliche Objekte in Python sind Strings, Integer, Long, Float, Tupelhttp://dict.tu-chemnitz.de/dings.cgi?query=immutable hat geschrieben:unveränderbar; unveränderlich; unabänderlich {adj} <=> immutable
Veränderliche Objekte sind Listen und Dictionaries.
Beispiele findest Du weiter oben im Thread.
Grüße,
der Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
- Michael Schneider
- User
- Beiträge: 569
- Registriert: Samstag 8. April 2006, 12:31
- Wohnort: Brandenburg
Man, das geht aber auch schnell hier... erst gestern immer auf das vorletzte Posting antwortet, heute schieben sich schon zwei dazwischen.
Michael
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
-
- User
- Beiträge: 312
- Registriert: Dienstag 24. Oktober 2006, 19:31
[/quote]
Unveränderliche Objekte in Python sind Strings, Integer, Long, Float, Tupel
Veränderliche Objekte sind Listen und Dictionaries.
Beispiele findest Du weiter oben im Thread.
Grüße,
der Michel[/quote]
Mann, ich Hirsch, weiss ich doch, aber immutables, also der englische Terminus war mir grad nicht geläufig-----
in Zukunft 5 Minuten nachdenken, bevor ich überflüssige Fragen stelle
Unveränderliche Objekte in Python sind Strings, Integer, Long, Float, Tupel
Veränderliche Objekte sind Listen und Dictionaries.
Beispiele findest Du weiter oben im Thread.
Grüße,
der Michel[/quote]
Mann, ich Hirsch, weiss ich doch, aber immutables, also der englische Terminus war mir grad nicht geläufig-----
in Zukunft 5 Minuten nachdenken, bevor ich überflüssige Fragen stelle