Matthew Tanous added the comment: It makes sense, except for this case is not true when "x" is an immutable data type - it appears as though something like [5] * n creates a list of totally separate elements (even if they start as the same thing).
It is difficult to see a case where I would not want separate elements from a mutable type as well. It would seem to me that having the "*" operator function as the list comprehension does now would be more logical and straightforward. This would change the default list in a way that is mostly unseen: [5] * 3 would still result in [5, 5, 5] while treating mutable nesting in a way that I believe would be more understandable from the apparent intent of the syntax in question. This would also resolve the problem of being unable to use the list multiplication to create a list of mutable objects. If I have a mutable object Foo and wish to create a list of different instances of them, I cannot use the straightforward syntax [Foo()] * n at present to do this, as there will only be one actual Foo instance in that list. I think that this is confusing to developers who would generally expect that this shortcut (and this is the only purpose of the operator for lists) would create a list of different instances. > On May 27, 2016, at 6:30 AM, Emanuel Barry <rep...@bugs.python.org> wrote: > > > Emanuel Barry added the comment: > > The reason why Python behaves like that in this case is a side-effect of the > way the data model is implemented. Lists are a mutable data type, which means > that referencing the same list - which is what you are doing - as opposed to > creating a new one each time, does exactly what is expected of the data > model, which is to keep a reference to the original list. Consider: > > x = ?? > y = x > > The object bound to `y` refers to the same object as the one bound to `x`, > such that `x is y`, for every possible value of `x`. As `=` is the assignment > operator (and not the copy operator, is such a thing existed), `y` merely has > a reference to `x`. > > There are very valid use cases where you will want to get a reference to the > original list to modify it, for example in a function that is meant to alter > the original. If you want a copy, use `l[:]` (or `l.copy()` in more recent > versions). > > In Python, every object and operation is evaluated once, when the interpreter > comes across it (in a for or while loop, it will come over the same point > multiple times, so it will evaluate it multiple times). By doing: > > [[x] * y] * n > > You are essentially doing this: > > l_1 = [x] # one-element list > l_2 = l_1 * y # list with `y` times `x` in it (references to `x`, not copies) > l_3 = [l_2] # a new list with one element, `l_2` > l_4 = l_3 * n # list with `n` times `l_3` in it (references to `l_3`, not > copies) > > As you can see, it makes no sense to have multiple different lists by doing > that. Doing a list comprehension, such as: > > [[None] * n for _ in range(N)] > > Will evaluate a new list each time the interpreter comes across it, which > will be N times for this case. Thus, you get a different list everytime. > > In other words, the reason that "That's just how it works" is because this > behaviour is a side-effect, not something that's out of the way. Creating a > new special case for this particular case seems like a very big stretch. > Remember, "Special cases aren't special enough to break the rules." > > This change that is "seemingly trivial" to you is actually asking to break > the Python semantics in some weird and convoluted way, for no gain since we > have list comprehensions (that you seem to already be acquainted with). > > Did that seem like a sufficient answer? ;-) > > ---------- > nosy: +ebarry > > _______________________________________ > Python tracker <rep...@bugs.python.org> > <http://bugs.python.org/issue27135> > _______________________________________ ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue27135> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com