sekomer
sekomer

Reputation: 742

Why do the list function and list literals act differently?

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?

Upvotes: 6

Views: 3366

Answers (1)

John Kugelman
John Kugelman

Reputation: 361977

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 characters
    list(('foo', 'bar')) == ['foo', 'bar'] # tuple
    list({'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:

Upvotes: 13

Related Questions