[Tutor] filling 2d array with zeros

Alex Hall mehgcap at gmail.com
Mon Sep 27 22:00:41 CEST 2010


On 9/27/10, Steven D'Aprano <steve at pearwood.info> wrote:
> 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) ]
That worked, and I think I see what is going on.
>
> 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.
That makes sense. Basically, the * operator in this case acts as a
copying command. For simple data types this is fine, but throw in a
complex type, in this case a list (though I expect that any object
would do this) and you are just doing what Python does to copy
objects: copying the memory location, not making a deep copy and
getting a duplicate object. I never would have thought of that. Thanks
again for the great explanation!
>
>
> --
> Steven D'Aprano
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> To unsubscribe or change subscription options:
> http://mail.python.org/mailman/listinfo/tutor
>


-- 
Have a great day,
Alex (msg sent from GMail website)
mehgcap at gmail.com; http://www.facebook.com/mehgcap


More information about the Tutor mailing list