views:

576

answers:

5

I'm beginning python and I'm trying to use a two-dimensional list, that I initially fill up with the same variable in every place. I came up with this:

def initialize_twodlist(foo):
    twod_list = []
    new = []
    for i in range (0, 10):
        for j in range (0, 10):
            new.append(foo)
        twod_list.append(new)
        new = []

It gives the desired result, but feels like a workaround. Is there an easier/shorter/more elegant way to do this?

+4  A: 
[[foo for x in xrange(10)] for y in xrange(10)]
Ignacio Vazquez-Abrams
+2  A: 

Usually when you want multidimensional arrays you don't want a list of lists, but rather a numpy array or possibly a dict.

For example, with numpy you would do something like

import numpy
a = numpy.empty((10, 10))
a.fill(foo)
Mike Graham
Although `numpy` is great, I think it might be a bit of overkill for a beginner.
voyager
numpy provides a multidimensional array type. Building a good multidimensional array out of lists is possible but less useful and harder for a beginner than using numpy. Nested lists are great for some applications, but aren't usually what someone wanting a 2d array would be best off with.
Mike Graham
+5  A: 

You can use a list comprehension:

x = [[foo for i in range(10)] for j in range(10)]
# x is now a 10x10 array of 'foo' (which can depend on i and j if you want)
Adam Rosenfield
+10  A: 

A pattern that often came up in Python was

bar = []
for item in some_iterable:
    bar.append(SOME EXPRESSION)

which helped motivate the introduction of list comprehensions, which convert that snippet to

bar = [SOME EXPRESSION for item in some_iterable]

which is shorter and sometimes clearer. Usually you get in the habit of recognizing these and often replacing loops with comprehensions.

Your code follows this pattern twice

twod_list = []                                       \                      
for i in range (0, 10):                               \
    new = []                  \ can be replaced        } this too
    for j in range (0, 10):    } with a list          /
        new.append(foo)       / comprehension        /
    twod_list.append(new)                           /
Mike Graham
+1 for teaching how to fish, instead of giving him the fish.
voyager
i want all the fish i can eat, so thanks
thepandaatemyface
By the way, [[foo]*10 for x in xrange(10)]can be used to get rid of one comprehension. The problem is that multiplication does a shallow copy, so new = [foo] * 10 new = [new] * 10will get you a list containing the same list ten times.
Scott Wolchok
Similarly, `[foo] * 10` is a list with the same exact `foo` 10 times, which may or may not be important.
Mike Graham
+1  A: 

This way is faster than the nested list comprehensions

[x[:] for x in [[foo]*10]*10]

Explanation:

[[foo]*10]*10 creates a list of the same object repeated 10 times. You can't just use this, because modifying one element will modify that same element in each row!

x[:] is equivalent to list(X) but is a bit more efficient since it avoids the name lookup. Either way, it creates a shallow copy of each row, so now all the elements are independent.

All the elements are the same foo object though, so if foo is mutable, you can't use this scheme., you'd have to use

import copy
[[copy.deepcopy(foo) for x in range(10)] for y in range(10)]
gnibbler
Why the downvote? Do you think this answer incorrect?
gnibbler