populating a doubly-subscripted array

G

ghw

What am I missing? I am using Python 3.1.2.

ff = [[0.0]*5]*5
ff #(lists 5x5 array of 0.0)
for i in range(5):
for j in range(3):
ff[j] = i*10+j
print (i,j,ff[j]) # correctly prints ff array values

ff # try this and see what happens!

result of first print of ff
[[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]]

result of second print of ff
0 0 0
0 1 1
0 2 2
1 0 10
1 1 11
1 2 12
2 0 20
2 1 21
2 2 22
3 0 30
3 1 31
3 2 32
4 0 40
4 1 41
4 2 42

result of third print of ff
[[40, 41, 42, 0.0, 0.0], [40, 41, 42, 0.0, 0.0],
[40, 41, 42, 0.0, 0.0], [40, 41, 42, 0.0, 0.0],
[40, 41, 42, 0.0, 0.0]]

Obviously there is something missing in my understanding of
how array values are populated. Why do all "rows" get
populated with the same set of values (40, 41, 42)?

Thanks for your help,
Hamilton Woods
 
M

Mark Wooding

What am I missing? I am using Python 3.1.2.

ff = [[0.0]*5]*5
ff #(lists 5x5 array of 0.0)
for i in range(5):
for j in range(3):
ff[j] = i*10+j
print (i,j,ff[j]) # correctly prints ff array values

ff # try this and see what happens!

result of third print of ff
[[40, 41, 42, 0.0, 0.0], [40, 41, 42, 0.0, 0.0],
[40, 41, 42, 0.0, 0.0], [40, 41, 42, 0.0, 0.0],
[40, 41, 42, 0.0, 0.0]]

Obviously there is something missing in my understanding of
how array values are populated. Why do all "rows" get
populated with the same set of values (40, 41, 42)?


[I suppose that the trailing 0.0 entries aren't in question: they're
because the individual rows have width 5 -- from `[0.0]*5' -- but only
the first three items of each is initialzed -- because j iterates only
over range(3).]

So, why do they all come out the same? The answer is because in fact
there are only two lists involved. You probably thought that you were
building something like the thing on the left. In fact, you have the
thing on the right. (Try to forgive the rubbish ASCII art.)

.--. .--.--.--.--.--. .--.
| ----->| | | | | | | --.
|__| `--^--^--^--^--' |__| \
| | .--.--.--.--.--. | | \
| ----->| | | | | | | ---. \
|__| `--^--^--^--^--' |__| \v
| | .--.--.--.--.--. | | \.--.--.--.--.--.
| ----->| | | | | | | ----->| | | | | |
|__| `--^--^--^--^--' |__| /`--^--^--^--^--'
| | .--.--.--.--.--. | | / ^
| ----->| | | | | | | --' /
|__| `--^--^--^--^--' |__| /
| | .--.--.--.--.--. | | /
| ----->| | | | | | | --'
`--' `--^--^--^--^--' `--'

What [x] * n does is make a list, whose length is n, and all of whose
entries are precisely the value x. If x itself is a list, then you get
an outer list all of whose entries are the /same/ inner list -- not
copies of it. So when you appear to change entries in one of the inner
lists, all the other inner lists seem to change too -- because they're
actually the same list.

-- [mdw]
 
M

Mark Wooding

Gregory Ewing said:
A reasonably elegant way to fix this is to use list comprehensions
for all except the innermost list:

ff = [[0.0]*5 for i in xrange(5)]

Yes, this is a good approach. I should have suggested something like
this as a solution myself, rather than merely explaining the problem.
If you're computing heavily with arrays, you might also consider
using numpy arrays instead of lists.

Also a good idea.

-- [mdw]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top