[Python] Onverklaarbaar List gedrag

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • Kraay89
  • Registratie: September 2012
  • Laatst online: 07-10 10:50
Zie hier het volgende stukje pyhton code:
Het begon als een poging Conway's Game of Life te simuleren. Hoe of wat ik dat wil is even niet relevant, maar het helpt misschien de variablenames te plaatsen. Ik heb er voor de vraag alle onnodigheden uitgesloopt.


Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import random

class world:
    #een world-class die (nog) niet veel om het lijf heeft. 2 variabelen en een functie.
    def __init__(self, x_axis, y_axis):
        self.x = x_axis
        self.y = y_axis

    def grid(self):
        newWorld = [[0]*self.x]*self.y
        newWorld[2][2] = 4
        print newWorld

myworld = world(4,4)
myworld.grid()


Als ik dit stukje code uitvoer dan print hij de volgende list:
code:
1
[[0, 0, 4, 0], [0, 0, 4, 0], [0, 0, 4, 0], [0, 0, 4, 0]]

In plaats van wat ik verwacht:
code:
1
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 4, 0], [0, 0, 0, 0]]


Waarom gebeurt dit? Bouw ik buiten mijn begrip om een soort dependancy in in de verschillende sublists? Heb ik iets gemist in python classes 101 en het gedrag van de self parameter?

Ik breek er al een paar uur mijn hoofd over maar ik kom er niet uit...

Beste antwoord (via Kraay89 op 14-10-2016 17:05)


  • Daedalus
  • Registratie: Mei 2002
  • Niet online

Daedalus

Moderator Apple Talk

Keep tryin'

>>> world = [[0]*4]*4
>>> world
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> [id(n) for n in world]
[4431462200, 4431462200, 4431462200, 4431462200]

Zoals je ziet heeft elke list in world dezelfde id, oftewel het verwijst naar hetzelfde object. Je world bestaat uit vier lijsten die allemaal naar dezelfde lijst verwijzen. Dit komt omdat de * operator n referenties van x objecten maakt, niet n kopieën. Zie ook Python Programming FAQ: How do I create a multidimensional list?.

Een mogelijke oplossing is iets te doen als:
Python:
1
[[0]*4 for i in range(4)]

[ Voor 11% gewijzigd door Daedalus op 14-10-2016 17:08 ]

“You know what I've noticed Hobbes? Things don't bug you if you don't think about them. So from now on, I simply won't think about anything I don't like, and I'll be happy all the time!” | 宇多田ヒカル \o/

Alle reacties


Acties:
  • Beste antwoord
  • 0 Henk 'm!

  • Daedalus
  • Registratie: Mei 2002
  • Niet online

Daedalus

Moderator Apple Talk

Keep tryin'

>>> world = [[0]*4]*4
>>> world
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> [id(n) for n in world]
[4431462200, 4431462200, 4431462200, 4431462200]

Zoals je ziet heeft elke list in world dezelfde id, oftewel het verwijst naar hetzelfde object. Je world bestaat uit vier lijsten die allemaal naar dezelfde lijst verwijzen. Dit komt omdat de * operator n referenties van x objecten maakt, niet n kopieën. Zie ook Python Programming FAQ: How do I create a multidimensional list?.

Een mogelijke oplossing is iets te doen als:
Python:
1
[[0]*4 for i in range(4)]

[ Voor 11% gewijzigd door Daedalus op 14-10-2016 17:08 ]

“You know what I've noticed Hobbes? Things don't bug you if you don't think about them. So from now on, I simply won't think about anything I don't like, and I'll be happy all the time!” | 宇多田ヒカル \o/


Acties:
  • 0 Henk 'm!

  • Kraay89
  • Registratie: September 2012
  • Laatst online: 07-10 10:50
Ugh, daar heb ik het niet in gezocht. Bedankt voor het snelle antwoord. Liever werken met loops of listcomprehensions dus om de lijst op te bouwen... (en uiteindelijk natuurlijk netjes naar een numpy array omzetten)

Hoe dan ook, Bedankt!

[ Voor 23% gewijzigd door Kraay89 op 14-10-2016 17:06 ]


Acties:
  • +1 Henk 'm!

  • Morrar
  • Registratie: Juni 2002
  • Laatst online: 09-10 13:33
Je kunt ook gewoon meteen met een numpy array beginnen: np.zeros((x_axis, y_axis)). Dan kun je daar later de waarden in zetten.

Zie ook: http://docs.scipy.org/doc...enerated/numpy.zeros.html

[ Voor 46% gewijzigd door Morrar op 14-10-2016 18:09 ]