-1

This is not the best way to create nested lists. Don't do it in your code. Do this instead. However, I'm curious about this way only.

Out of curiosity. I tried googling but all I got is how to do it and not why, and I already know that part.

I was trying to instantiate the following structure with a multiplier:

[[], [], []]

from an unknown number of inner lists, so I wanted to multiply the lists by range(len(other_list)) (this last part is unrelated, so I´ll simplify multiplying by 3 here).

After failing intuitively, with the following expression: [[]] *3, I learned in another question that you need to represent as multiplying both lists (inner ones and one outer each) instead.

>>[[]] * 3
[[], [], []]
>>[[] * 3]
[[]]
  • Why the sentence works that way (it's kind of multiplying the double list first and then doing and extend of the outer list...?)
  • Python is usually very intuitive in all its expressions. What makes this one different?

Thanks for the patience. I know this is a weird question :D

Natacha
  • 1,132
  • 16
  • 23
  • 2
    *"I learnt in another question ..."* - Which one? I'd like to see that. – Kelly Bundy Jul 24 '22 at 04:28
  • 1
    @Natacha Here is an analogy. Consider the difference between these two statements: `[60 for _ in range(3)]` and `[[60] for _ in range(3)]`. The same thing applies in the case of expressions inside and outside of the list: `[] for _ in range(3)` fails to return anything due to syntax error, but if it didn't it would amount to "give me this exact value three times in a row", whereas this expression inside a list is interpreted simply as "give me three copies of this exact list, whatever may be inside of it". – Somebody Out There Jul 24 '22 at 04:32
  • 1
    You probably want to look [here](https://stackoverflow.com/questions/240178/list-of-lists-changes-reflected-across-sublists-unexpectedly) before you get too far. Instantiating the list like that will lead to lots of issues. – BeRT2me Jul 24 '22 at 04:37
  • @BeRT2me Thanks! I saw the same answer and my code went back to my list comprehension way. I was working with tuples anyway, but as a good practice is better. However, this question is just out of curiosity about this particular sentence, no matter the bugs that its usage could cause. Consider me aware of that and bear with me on this :) – Natacha Jul 24 '22 at 04:46

1 Answers1

3

It all comes down to how list multiplication is implemented. Unlike numeric values, there isn't a standard idea of what multiplication should mean for a list. There is a great argument that multiplication is meaningless for lists and that an error should be raised.

But the implementers like to do clever things and assigned a meaning to the mathematical operators. For multiplication, the list is extended length * N elements and the existing values are used to to fill the space. I think the primary motivation is to have a convenient way to prefill a list with default values.

In the first case [[]] * 3 you have a list with a single value: another list. The list is extended to 3 elements and new references to that single list are filled. The print shows [[], [], []] but somewhat subtly, that's really just 3 references to the single list you started with.

In the second case [[] * 3] you extend an empty inner list and put the result in an outer list. But that extension is 0 * N because there isn't anything in the list, so you just end up with [[]].

Different collections may choose to do something completely different. If you had a numpy array arr, then arr * 3 would multiple each value in arr by 3 and return to you a new array with the result.

tdelaney
  • 73,364
  • 6
  • 83
  • 116
  • 2
    @DanielHao - I'm not sure where its documented other than a mention in [Emulating container types](https://docs.python.org/3/reference/datamodel.html#emulating-container-types) _ sequence types should implement addition (meaning concatenation) and multiplication (meaning repetition) by defining the methods __add__(), __radd__(), __iadd__(), __mul__(), __rmul__() and __imul__()_ – tdelaney Jul 24 '22 at 15:36