I was trying to create a list with n empty lists inside of it, but faced an interesting situation.

Firstly I tried the following:

>>> n = 3>>> list([]) * n[]

It creates an empty list.

After that I tried the following line, which creates an empty list, too:

>>> list(list()) * n[]

But when I try the same with literals,

>>> [[]] * n [[], [], []]

it gives the correct output. Can someone explain why?

1

Best Answer


list(...) is not interchangeable with [...]. You can wrap square brackets around things to get nested lists, but wrapping things in list() doesn't have the same effect.

  • When you write [[]] you get a list with a single element. That element is [].

  • When you write list([]) the list constructor takes an iterable and creates a list with the same elements. If you wrote list(['foo', 'bar']) the result would be ['foo', 'bar']. Writing list([]) yields [].

    This form is more useful when you pass iterables that aren't lists. Other examples:

    list('abc') == ['a', 'b', 'c'] # strings are iterables over their characterslist(('foo', 'bar')) == ['foo', 'bar'] # tuplelist({'foo', 'bar'}) == ['foo', 'bar'] # set; could get ['bar', 'foo'] instead
  • list(list()) is equivalent to list([]). And we've seen that's in turn equivalent to [].

Stay away from [[]] * n when creating a multidimensional list. It will create a list with n references to the same list object and will bite you when you try to modify the internal lists. It's a common mistake that everyone makes. Use this instead, which will create a separate empty list for each slot:

[[] for i in range(n)]

Further reading:

  • How to create a multi-dimensional list
  • List of lists changes reflected across sublists unexpectedly