Python - dynamic nested list

So, I'm trying to create a nested list in Python based on width and height. This is what I still have:

width = 4 height = 5 row = [None]*width map = [row]*height 

Now this is obviously not entirely correct. When printed, it looks fine:

 [[None, None, None, None], [None, None, None, None], [None, None, None, None], [None, None, None, None], [None, None, None, None]] 

But an attempt to assign a value to this position:

 map[2][3] = 'foo' 

I get:

 [[None, None, None, 'foo'], [None, None, None, 'foo'], [None, None, None, 'foo'], [None, None, None, 'foo'], [None, None, None, 'foo']] 

It is clear that this is because each sublist really just refers to the same object, row, so it changes one, it changes them all. So this is the closest I have!

How can I dynamically generate a nested list? Thanks!

+6
python list nested
source share
2 answers

When you execute [row]*height , you get the same list object on each line. The reference to the row array is repeated on each line, which means that each line actually points to the same list object. Therefore, changing one row actually changes all rows.

See what happens when you type id() for each line. They are all the same!

 >>> grid = [[None] * width] * height >>> [id(row) for row in grid] [148014860, 148014860, 148014860, 148014860, 148014860] 

You can force python to generate separate but identical lists for each line using list comprehension. When you use [rowexpr for i in xrange(height)] , then rowexpr will be evaluated once per row. The trick then is to use an expression that will result in a unique list every time it is evaluated.

This will make more sense if you see it in action:

 >>> grid = [[None] * width for i in xrange(height)] >>> grid[2][3] = 'foo' >>> grid [[None, None, None, None], [None, None, None, None], [None, None, None, 'foo'], [None, None, None, None], [None, None, None, None]] 

Each time [None] * width is evaluated, it generates a new list.

 >>> [id(row) for row in grid] [148016172, 148015212, 148016236, 148016108, 148016332] 
+11
source share

I am using something like this:

 w = 5 h = 5 map = [] for i in range(h): row = [] for j in range(w): row.append(None) map.append(row) print map map[2][3] = 'foo' print map 
0
source share

All Articles