Problem mit Matrix - Warum?!

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
mynamenixname
User
Beiträge: 2
Registriert: Dienstag 25. Januar 2011, 19:40

Hallo,
ich bin ganz neu mit Python unterwegs, also bitte seid nicht zu kritisch mit mir :wink: .
Das unten dargestellte Programm soll eine 10*10er Matrix mit maximal 5 1en ausgeben. Nun "zieht" er leider im Streifen, das heißt er verteilt zwar ganz toll die 1en in der Matrix, allerdings sind alle sind alle Zeilen identisch => so 20-50 1er :!: .
Ich habe bereits versucht meinen Fehler zu finden, aber irgendwie wirkt auf mich alles schlüssig :?: :!: .

Vielen Dank schon einmal für eure Hilfe.

Code: Alles auswählen

#	CREATE CLEAR GRID
def ccgrid():
	line	=	[0,	0,	0,	0,	0,	0,	0,	0,	0,	0]
	grid	=	[line, line, line, line, line, line, line, line, line, line]
	return grid

	
#	CREATE MAX X 1s
def	cmxo(grid, max):
	import random
	for i in range(1, max):
		x = random.randint(0, 9) 
		y = random.randint(0, 9) 
		line	= grid[x]
		line[y]	= 1
		grid[x]	= line
		# oder halt grid[x][y]
	return grid
	
	
#	MAIN	
def main():
	grid = ccgrid()
	grid = cmxo(grid, 5)
	print grid
	
main()
BlackJack

Mal sehen:

Code: Alles auswählen

In [203]: line   =   [0,   0,   0,   0,   0,   0,   0,   0,   0,   0]

In [204]: grid   =   [line, line, line, line, line, line, line, line, line, line]

In [205]: grid
Out[205]: 
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

In [206]: grid[0][0] = 42

In [207]: grid
Out[207]: 
[[42, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [42, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [42, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [42, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [42, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [42, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [42, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [42, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [42, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [42, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

In [208]: grid[0] is grid[1]
Out[208]: True
`grid` ist eine Liste in der 10 mal *die selbe* Liste steckt. Du musst da 10 Listen reinstecken und nicht immer nur die eine.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Du hast 10x das selbe Listenobjekt, welches Du in Deine grid-Liste packst. Kleines Beispiel, was das verdeutlicht:

Code: Alles auswählen

In [13]: line = [0] * 10

In [14]: line
Out[14]: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

In [15]: grid = [line] * 2

In [16]: grid
Out[16]: [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

In [17]: grid[0] is grid[1]
Out[17]: True
Wie man anhand des Identitätvergleichs (is) sieht, handelt es sich hier um identische Objekte. Daher führt das zu folgendem Ergebnis:

Code: Alles auswählen

In [18]: grid[0][4] = 42

In [19]: grid
Out[19]: [[0, 0, 0, 0, 42, 0, 0, 0, 0, 0], [0, 0, 0, 0, 42, 0, 0, 0, 0, 0]]
Obwohl man vermeindlich nur in der ersten Zeile von "grid" etwas ändert, taucht die 42 mehrfach auf. Einfach weil es sich um ein und das selbe Objekt handelt :-)

Darauf fallen ürbigens viele Neulinge rein ;-)

Um das zu vermeiden, musst Du 10x eine neue Liste für die Zeilen aufbauen:

Code: Alles auswählen

In [20]: grid = []

In [21]: for line in xrange(10):
   ....:     grid.append([0]*10)
   ....:
   ....:

In [22]: grid[0] is grid[1]
Out[22]: False
Oder kürzer als List-Comprehension:

Code: Alles auswählen

In [33]: grid = [[0]*10 for _ in xrange(10)]
Zu Deinem Code ein paar Anmerkungen:

- wie haben im Forum spezielle Tags für Python-Code; da hat man dann hübsches Syntax-Highlighting ;-)

- in Python sind nach PEP8 4 Spaces als Einrückung Standard

- Module sollte man normalerweise nicht innerhalb von Funktionen importieren

- Deine Funktionsnamen sind schlecht gewählt; du kommentierst sie ja bereits ;-) Nimm lieber sofort einleuchtende Namen!

- Deine main()-Funktion wird so immer aufgerufen. Schreib das lieber so:

Code: Alles auswählen

if __name__ == "__main__":
    main()
- Dein Kommentar "# oder halt grid[x][y]" enthält den schönen Weg, die Zuweisung zu gestalten.

Mist, BlackJack war schneller... naja, hab mir so viel Mühe gegeben, daher schicke ich es auch ab :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
mynamenixname
User
Beiträge: 2
Registriert: Dienstag 25. Januar 2011, 19:40

vielen, vielen Dank, darauf wäre ich nie gekommen :)
Antworten