Seite 1 von 1

Tupel mit list-Elementen

Verfasst: Montag 19. April 2010, 12:33
von Goswin
Es heißt zwar immer, dass Tupel ganz _unveränderbar_ sind (weshalb ich im folgenden Codestück eine Fehlermeldung erwartet hatte), aber siehe, es funktioniert trotzdem:

Code: Alles auswählen

a = [1,2]
b = [3,4]
tt = [a,b]  #Tippfehler; mit tt = (a,b) funkts aber immer noch!
print(tt)
tt[0][0] = 0
print(tt)
Was passiert hinter den Kulissen, wenn ich ein einzelnes Element der "Matrix" tt ändere? Wird das gesamte Tupelobjekt tt neu gebaut und das alte verworfen, oder wird nur das entsprechende Listenelement ersetzt?

Verfasst: Montag 19. April 2010, 12:38
von mkesper

Code: Alles auswählen

In [1]: a = [1, 2]

In [2]: type(a)
Out[2]: <type 'list'>

In [3]: b = [3, 4]

In [4]: type(b)
Out[4]: <type 'list'>

In [5]: tt = [a, b]

In [6]: type(tt)
Out[6]: <type 'list'>

In [7]: a = (1, 2)

In [8]: type(a)
Out[8]: <type 'tuple'>

Verfasst: Montag 19. April 2010, 12:42
von BlackJack
@Goswin: In Deinem Quelltext kommt gar kein Tupel vor, sondern nur Listen.

Und es wird nur die Liste verändert, denn darauf bezieht sich die Zuweisung letztendlich nur. Hinter den Kulissen passiert folgendes:

Code: Alles auswählen

x[i][j] = v
# ->
x.__getitem__(i).__setitem__(j, v)
Das *Tupel* wird in Deinem Fall (ich nehme mal an `tt` sollte eigentlich eins sein) nicht verändert. Von dem wird nur das Listenobjekt erfragt.

Verfasst: Montag 19. April 2010, 12:46
von Goswin
Ops, ich hatte oben mich verschrieben... Ich meinte natürlich was folgt:

Es heißt zwar immer, dass Tupel ganz _unveränderbar_ sind (weshalb ich im folgenden Codestück eine Fehlermeldung erwartet hatte), aber siehe, es funktioniert trotzdem:

Code: Alles auswählen

a = [1,2]
b = [3,4]
tt = tuple((a,b))
print(tt)
tt[0][0] = 0
print(tt)
Was passiert hinter den Kulissen, wenn ich ein einzelnes Element der "Matrix" tt ändere? Wird das gesamte Tupelobjekt tt neu gebaut und das alte verworfen, oder wird nur das entsprechende Listenelement ersetzt?

Verfasst: Montag 19. April 2010, 12:49
von .robert
Das Tupel tt enthält ja nur Referenzen auf Listenobjekte. Wenn du eine der Listen Modifizierst, änderst du ja nicht die Referenz, sondern die Liste. Und das geht.

Verfasst: Montag 19. April 2010, 13:02
von BlackJack
@Goswin: Jetzt wolltest Du wohl *ganz* gründlich sein. :-) Du gibst der `tuple()`-Funktion bereits ein Tupel. Dadurch wird es nicht doppelt so "tupelig" ;-) Es würde sogar ``tt = a, b`` genügen. Nur eckige Klammern darf man halt nicht setzen.

Verfasst: Montag 19. April 2010, 13:05
von Goswin
@.robert:
Wenn ich eine groooße Matrix habe, ist die Änderung eines Einzelelements dann wohl schneller bei einem _Tupel_ voller Listen als bei einer _Liste_ voller Listen?

Verfasst: Montag 19. April 2010, 13:11
von .robert
"premature optimization is the root of all evil"

Triff die Wahl ob List oder Tupel danach, was für Funktionen du brauchst, nicht was schneller ist.
Aber Tupel sind vor allem effizienter mit dem Speicherplatz, da Listen "auf Verdacht" Speicher vor reservieren.

Verfasst: Montag 19. April 2010, 13:13
von jbs
Goswin hat geschrieben:@.robert:
Wenn ich eine groooße Matrix habe, ist die Änderung eines Einzelelements dann wohl schneller bei einem _Tupel_ voller Listen als bei einer _Liste_ voller Listen?
Willst du numpy verwenden? Aber was verstehst du unter groß?

Verfasst: Montag 19. April 2010, 13:15
von Goswin
BlackJack hat geschrieben:Es würde sogar ``tt = a, b`` genügen. Nur eckige Klammern darf man halt nicht setzen.
In der Tat, wenn wir das "nur" nicht zu wörtlich nehmen. Ich falle immer wieder auf die Schreibweise "tt = tuple(a,b)" herein, was ja paradoxerweise auch falsch ist... :P

Verfasst: Montag 19. April 2010, 13:30
von Goswin
.robert hat geschrieben:"premature optimization is the root of all evil"
"It is never too early to think about performance",
Rebecca Parsons in "97_Things Every Software Architect Should Know", O'Reilly, 2009.
Tja, so schnell veralten die Weisheiten :wink: !

Aber meine Matrix hat unveränderliche Dimensionen, da werden die Tupel wohl etwas speichersparend sein.
Vielen Dank für eure Hinweise.

Verfasst: Montag 19. April 2010, 13:38
von cofi
Goswin hat geschrieben:
.robert hat geschrieben:"premature optimization is the root of all evil"
"It is never too early to think about performance",
Rebecca Parsons in "97_Things Every Software Architect Should Know", O'Reilly, 2009.
Tja, so schnell veralten die Weisheiten :wink: !
Naja im 2. Quote geht es wohl v.a. um Designentscheidungen (-> Architect), die sind nur schlecht wieder gerade zu biegen. Und um so eine handelt es sich hier IMO durchaus, mit Tupeln und Listen kann und muss man anders arbeiten.

Verfasst: Montag 19. April 2010, 13:50
von jbs
@Goswin: Ich frag nochmal, wie groß ist denn deine Matrix?

Verfasst: Montag 19. April 2010, 14:06
von Darii
Goswin hat geschrieben:@.robert:
Wenn ich eine groooße Matrix habe, ist die Änderung eines Einzelelements dann wohl schneller bei einem _Tupel_ voller Listen als bei einer _Liste_ voller Listen?
Nein, das wird keinen Unterschied machen.

Aber vermutlich wills du wirklich ein numpy-Array verwenden. Das ist schneller und verbraucht vor allem massiv weniger Speicher. Einem Numpy-Array liegt ein C-Array zugrunde, d.h. es braucht nur so viel Speicher wie die Daten auch brauchen. Deine Konstruktion braucht erstmal den Speicher für die Zeiger, die Listenobjekte und die Daten(die auch Python-Objekte sind und Speicher fressen). Tippe mal drauf, dass das mindestens einen Faktor 4 ausmachen wird. Alternativ kannst du auch ein array.array nehmen.

Verfasst: Montag 19. April 2010, 14:21
von Goswin
jbs hat geschrieben:@Goswin: Ich frag nochmal, wie groß ist denn deine Matrix?
Diese Frage ist falsch gestellt (je größer meine Matrix sein darf, desto mehr Events kann ich in Realzeit analysieren).

@Radii: Ja, vermutlich sollte ich numpy benutzen.