Bug or not ?

Alex Martelli aleaxit at yahoo.com
Fri May 4 09:24:25 EDT 2001


"jay graves" <jgraves3 at austin.rr.com> wrote in message
news:3af296d9.40589285 at news-server.austin.rr.com...
    [snip]
> >>> x =[[0]*2] * 2
> >>> x
> [[0, 0], [0, 0]]
    ...
> As you can see, x[0] and x[1] point to the same object and likewise
> x[a][b] where a = 0,1 and b = 0,1 are the same object.

Right.  You can check this with the built-in function id():

>>> x=[[0]*2]*2
>>> id(x[0])
8340604
>>> id(x[1])
8340604
>>> id(x[0][0])
8137500
>>> id(x[0][1])
8137500
>>> id(x[1][0])
8137500
>>> id(x[1][1])
8137500
>>>

The exact numbers returned by id() will differ, but the
pattern of equality will remain more or less the same.

Now, you only care about this when some reference is to
a MUTABLE objects.  An IMMUTABLE object, such as a
number, may always be "cached"/"interned" by some
versions of the interpreter...:

>>> a=0
>>> b=0
>>> id(a)
8137500
>>> id(b)
8137500
>>>

...so we don't really care about that; don't test with
the 'is'/'is not' operator when immutable objects are
involved, because the results may not be portable to
all versions of Python...!


> I usually create this kind of construction using loops as opposed to
> the * operator.  Hopefully one of the bots (or someone else) will jump
> in and show us t.3.1est way to do this.

"t.3.1est"...?

The best way to make a list of N references to a certain
immutable object (e.g., a number) is [thatobject]*N.  As
I try to explain above, you don't care (and can't control)
whether separate references to immutable objects with
identical values have the same identity or not.

The best way to make a list of N references to *separate
copies* of a certain *mutable* object (e.g., a list) is
often a loop of some kind.  The handiest kind, in particular,
is often a list comprehension, e.g.:

    x = [ [0]*N for i in range(M) ]

is a good way to have x refer to a list of M separate
copies of lists, each of N references to integer 0.  But
of course there are other "look, ma, no [explicit] loop"
ways, e.g.:

    x = map(list, [[0]*N]*M)

or the very general:

    import copy
    x = map(copy.copy, [[0]*N]*M)

which will work for other kinds of mutable objects to
which copy.copy can be applied (you may also choose to
use copy.deepcopy here, in certain cases).


Personally, I find the list comprehension clearest and
most readable in most such cases, so that's what I'd
normally use.


Alex






More information about the Python-list mailing list