Re: surprising behavior of chained initializations

Guido.van.Rossum@cwi.nl
Thu, 26 Jan 1995 22:45:27 +0100

> I believe I understand the behavior of the following script, but I
> don't like it:
>
> >#!/usr/local/bin/python
> >
> >a = b = []
> >
> >a.append("x")
> >b.append("y")
> >
> >print b
>
> The output is "['x', 'y']". I think the naive observer would
> expect "['y']" as the output. Shouldn't the left-hand sides of
> multiple initializations get copies of the right-hand sides, instead
> of name aliases (or whatever)?

Well, apparently *one* naive observer expected "['y']". I don't think
observations of naive observers generalize in a regular way :-)

The idea here is that "a = b = expression" has the same effect (except
for side effects in the calculation of b) as "b = expression; a = b".
It is very fundamental to Python that after "a = b", a and b refer to
the same *object*, and that modification of that *object* are seen
independent of the access path. Note that in "b = []; a = b; a =
[1]", the last assignment only changes a's binding; it leaves the
object that a pointed to before the assignment unchanged.

If you want to initialize multiple variables to distinct empty lists,
you'll have to write, for instance

a, b = [], []

Note that there's a rule in the language that each evaluation of []
yields a distinct list object (as do all other list displays,
e.g. [1,2]). This rule does not apply to expressions yielding
immutable objects, like 0 or "abc" or (); it is a permissible
optimization to make all or some occurrences of such expressions yield
the same object.

--Guido van Rossum, CWI, Amsterdam <mailto:Guido.van.Rossum@cwi.nl>
<http://www.cwi.nl/cwi/people/Guido.van.Rossum.html>