On Tue, 28 Sep 2010 03:54:55 am Alex Hall wrote:
Hi again everyone,
I have a 2d array (I guess it is technically a list) which I want to
fill with zeros. Later I will change some values, but any I do not
change have to be zeros. I have two complex for loops, but I tried to
scale things down to a couple list comprehensions and I broke things.
What is wrong with the following line?
self.am=[[(a,b) for a in range(len(self.lines)) a=0] for b in
range(len(self.lines)) b=0]
Start with a single row, of n columns:
[0 for i in range(n)] # the loop variable i is not used
Now all you need is to set n appropriately:
n = len(self.lines)
[0 for i in range(n)]
Is there an easier way? Yes, you don't even need a list comp:
[0]*n
Now make m rows of the same:
[ [0]*n for i in range(m) ]
And you are done.
You might be tempted to take a short-cut:
[ [0]*n ]*m
but this doesn't work as you expect. This is one of the rare Python
gotchas -- it looks like it should work, but it doesn't behave like you
might expect. Try it and see:
a = [[0]*3]*4
a
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
a[0][1] = 2
a
[[0, 2, 0], [0, 2, 0], [0, 2, 0], [0, 2, 0]]
What's going on here? It's a little complicated, so let's start with a
simpler situation:
b = [0, 0, 0]
c = b # c is an alias to the same list as b
d = b # so is d
e = c # and e
b[0] = 3
e
[3, 0, 0]
Because both b and e refer to the same list (not copies!) any change to
b *must* also change e. It's like if Barack Obama gets a haircut, so
does the current President of the USA, because they're the same person.
Now stick them in a list:
a = [b, c, d, e]
a
[[3, 0, 0], [3, 0, 0], [3, 0, 0], [3, 0, 0]]
a[0][1] = 4
a
[[3, 4, 0], [3, 4, 0], [3, 4, 0], [3, 4, 0]]
Modify one, modify them all, because in fact they are actually all the
same list.
[ [0]*3 ]*4 behaves the same way. There's no problem in the inner list,
but the outer list doesn't make four copies of [0,0,0], it has *one*
list repeated four times. Modify one, modify them all.