Duplicated List...

Alex Martelli aleaxit at yahoo.com
Tue Dec 26 10:43:08 CET 2000

"dyo" <dyo at shinbiro.com> wrote in message
news:929lq7$ds1$1 at hiline.shinbiro.com...
> Hi everyone.
> >>> a=[1,2,3]
> >>> b=[a,10,20,30]
> >>> b[0].append('x')
> >>> b
> [[1, 2, 3, 1, 2, 3, 'x'], 10, 20, 30]

No way.  You must be doing something different if this
is the output you observe -- e.g. the first statement
must be

>>> a = [1,2,3] * 2

or something similar.

Anyway, after these statements, the reference named
'a' and the one at index 0 in list b are currently bound
to the same object.  Besides modifying that object, a
simple way to check is with the id function:

>>> a=[1,2,3]
>>> b=[a,4,5]
>>> b
[[1, 2, 3], 4, 5]
>>> id(a)
>>> id(b[0])

The id that comes out for you will be arbitrary, of course,
but it will be the same for both references -- as they're
bound to the same object.  OK so far?  Whatever mutators
you call on that object, it keeps its identity, and those
mutator methods do NOT affect *the references*, but
rather *the object*:

>>> a.append('x')
>>> a
[1, 2, 3, 'x']
>>> b
[[1, 2, 3, 'x'], 4, 5]
>>> id(a)
>>> id(b[0])

.append is a mutator, the object's current state changes,
but of course its identity doesn't, and nor do the references
that currently happen to be bound to it.

Mutating an object of a given identity is an utterly different
and unrelated issue from binding and rebinding references
to objects...:

> >>> a=[1,1000]

This rebinds the named-reference (aka 'variable') "a"
to something completely different, severing previous
bounds of that reference.

>>> a=[1,1000]
>>> id(a)
>>> id(b[0])

See?  *a*, the named-reference, is affected: it is now
bound to an object with a different identity.  The object
that was previously referred-to by a is supremely
unaffected and indifferent, as are any other references
to it that were previously around -- they all still are.

> >>> a
> [1, 1000]
> >>> b
> [[1, 2, 3, 1, 2, 3, 'x', 'xxx'], 10, 20, 30]
> >>>
> Why do not change List 'b' ?
> What happen List 'b' ?

b[0] still refers to whatever it was referring to before a
was re-bound.

If you think of '=' as "assignment", as the docs call it,
and know about 'assignment' from such languages as
C, Fortran, Pascal, you're never going to make heads or
tails of languages with reference-semantics, such as
Python or Java. That's why I prefer to call '=' "rebinding".

[although THAT irks people whose backgrounds are in
other languages such as LISP -- I'll freely admit that
Python's "=" is close to a LISP setq, which is normally
called 'assignment', not to a LIST let...]

There are objects, and there are references to objects
(which live in various 'slots', some named, some indexed;
no real difference).  Mutator methods affect objects;
rebinding ('assignment') affects references.  Keep this
distinction in mind, and everything will eventually fall
into place...


More information about the Python-list mailing list