[Tutor] Weird list indexing
Danny Yoo
dyoo@hkn.eecs.berkeley.edu
Wed Jul 9 17:26:02 2003
On Wed, 9 Jul 2003, Zak Arntson wrote:
> Now, why does this happen? I'm using Python 2.2.3, by the way.
>
> ###
>
> >>> a = [[None] * 3] * 3
> >>> a
> [[None, None, None], [None, None, None], [None, None, None]]
> >>> a[1][2] = 'a'
> >>> a
> [[None, None, 'a'], [None, None, 'a'], [None, None, 'a']]
>
> ###
>
> My guess is that the three lists are all the same object, just pointed to
> three different times? So it seems my shortcut to create a two-dimensional
> array doesn't work. Is there better shortcut?
Yes, exactly.
A common idiom for making 2d arrays in Python is a list comprehension
approach:
###
>>> a = [ [None] * 4
... for i in range(7) ]
>>> a
[[None, None, None, None],
[None, None, None, None],
[None, None, None, None],
[None, None, None, None],
[None, None, None, None],
[None, None, None, None],
[None, None, None, None]]
>>> a[1][1] = "Foo!"
>>> a
[[None, None, None, None],
[None, 'Foo!', None, None],
[None, None, None, None],
[None, None, None, None],
[None, None, None, None],
[None, None, None, None],
[None, None, None, None]]
###
This works because the subexpression in our list comprehension,
[ [None] * 4 for i in range(7) ]
^^^^^^^^^^
is evaluated more than once. We get a new sublist for each row in our
matrix, so we're able to avoid the shared-structure problem that you saw.
Now that we know this, we can make a small utility function to construct
2d arrays for us:
###
>>> def makeArray(rows, cols):
... return [ [None] * cols for i in range(rows) ]
...
>>> makeArray(2, 3)
[[None, None, None],
[None, None, None]]
###
Good luck to you!