Problem with storing widgets in a list

Ah, you have fallen into the SECOND of the classic Python blunders: the "two-dimensional list" blunder. Before you read ahead to the answer, you might want to run the following experiment at a command line:

    x = [[0]*5]*7
    x
    x[0][0] = 1
    x

Let's look at [[0]*5]*7. First, Python handles the inner part ([0]*5). This creates a list with 5 references to the constant 0. If you set any element to something else, it creates a new reference. Everything works perfectly.

Now, it handles the outer part, the *7. What this does, perhaps unexpectedly, is create a list containing 7 references to your first list. It does NOT create 7 different list objects! When that statement is done, you will have created exactly two lists: one contains five references to 0, and one contains 7 references to the first list.

So, when you change x[0][0], it also affects x[1][0], x[2][0], x[3][0], etc, because x[0] and x[1] are bound to the SAME LIST.

One solution to this is to create:
    x = [[0]*5, [0]*5, [0]*5, [0]*5, [0]*5, [0]*5, [0]*5]

However, I usually try to build up complicated data structures like this by starting from a null list and appending until I have what I need, specifically because of this trap. However, don't try to do this:
    x = *7
because that has exactly the same problem.

Note that you do not need to say [0,] to create a 1-element list, like you do with a tuple.

···

On Wed, 9 Apr 2008 18:43:17 -0600, "Daniel Gee" <zefria@gmail.com> wrote:

I'm trying to make a tile "engine" for a game, and my current design is to
have a 2d list of panels (which do the custom drawing) and then place the
panels into an appropriate grid sizer. However, when I try to access the
panels within the 2d list then either the wrong panels are accessed or the
panel data isn't changed so they don't change their image at all.
  
--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

NEVER go in against a Sicilian when death is on the line! Hah hah hah h…

···

On Thu, Apr 10, 2008 at 10:24 AM, C M cmpython@gmail.com wrote:

Ah, you have fallen into the SECOND of the classic Python blunders: the

“two-dimensional list” blunder.

As an aside, I would love to read a short web page or such (of The

Classic Python Blunders. If it doesn’t exist, I encourage you to

write it and add it to the wiki or somewhere.


www.fsrtechnologies.com

Tim Roberts wrote:

One solution to this is to create:
   x = [[0]*5, [0]*5, [0]*5, [0]*5, [0]*5, [0]*5, [0]*5]

Even better is to bite the bullet, install numpy, and use a real 2-d array:

x = numpy.zeros((5,7))

get an element:

e = x[3,2]

get a row

r = x[3,:]

get a column

c = x[:,2]

and you can put any python object into an array, not just numbers:

x = numpy.empty((5,7), dtype=numpy.object)

x[3,2] = wx.Button(....)

Any many more nifty features....

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov