On Sun, Nov 4, 2012 at 10:27 PM, Demian Brecht <demianbre...@gmail.com> wrote: > So, here I was thinking "oh, this is a nice, easy way to initialize a 4D > matrix" (running 2.7.3, non-core libs not allowed): > > m = [[None] * 4] * 4 > > The way to get what I was after was: > > m = [[None] * 4, [None] * 4, [None] * 4, [None * 4]] > > (Obviously, I could have just hardcoded the initialization, but I'm too lazy > to type all that out ;)) > > The behaviour I encountered seems a little contradictory to me. > [None] * 4 creates four distinct elements in a single array > while [[None] * 4] * 4 creates one distinct array of four distinct elements, > with three references to it:
Incorrect. In /both/ cases, the result is a list of length 4, whose elements are 4 (references to) the exact same object as the original list's element. Put simply, the list multiplication operator never copies objects; it just makes additional references to them. However, unlike a list object (as in your latter example), the object `None` is completely immutable (and what's more, a singleton value), so you just-so-happen *not to be able to* run into the same problem of mutating an object (assignment to an index of a list constitutes mutation of that list) that is referenced in multiple places, for you cannot mutate None in the first place!: >>> x = None >>> x.a = 42 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'NoneType' object has no attribute 'a' >>> # it doesn't overload any mutating operators: >>> type(None).__dict__.keys() ['__hash__', '__repr__', '__doc__'] >>> # and it obviously has no instance variables, >>> # so, we can't modify it in any way whatsoever! (Lists, on the other hand, define item assignment, .pop(), .remove(), and a few other mutator methods.) >>>> a = [None] * 4 >>>> a[0] = 'a' >>>> a > ['a', None, None, None] > >>>> m = [[None] * 4] * 4 >>>> m[0][0] = 'm' >>>> m > [['m', None, None, None], ['m', None, None, None], ['m', None, None, None], > ['m', None, None, None]] > > Is this expected behavior Yes. It's also a FAQ: http://docs.python.org/2/faq/programming.html#how-do-i-create-a-multidimensional-list > and if so, why? It's a general (albeit AFAIK unstated) principle that Python never copies objects unless you explicitly ask it to. You have encountered one example of this rule in action. > In my mind either result makes sense, but the inconsistency is what throws me > off. It is perfectly consistent, once you understand what list multiplication actually does. Cheers, Chris -- http://rebertia.com -- http://mail.python.org/mailman/listinfo/python-list