I am trying to understand chain assignment in Python.
If I run x = x[1] = [1, 2]
, I get an infinite list [1, [...]]
.
But if I run x = x[1:] = [1, 2]
, I will get a normal list [1, 1, 2]
.
How does it work in the background to make these two different results?
First, understand that in a chained assignment, the right-most expression is evaluated to an object. A reference to that object is then assigned to each target in sequence, from left to right. x = y = z
is effectively the same as
t = z # A new temporary variable "t" to hold the result of evaluating z
x = t
y = t
del t
Second, you need to understand the difference between assigning t
to the subscription x[1]
and to the slicing x[1:]
. In the former, element 1 of x
is replaced by t
. In the latter, elements x[1]
, x[2]
, etc are replaced by t[0]
, t[1]
, etc, extending or shrinking x
as necessary.
The first example is equivalent to
t = [1,2]
x = t
x[1] = t
del t
x[1]
becomes a reference to x
itself; list.__repr__
can detect cycles like this and represents them with ...
. x
, x[1]
, x[1][1]
, etc are all references to the original list [1,2]
.
The second example is equivalent to
t = [1,2]
x = t
x[1:] = t
del t
In this case, no cycles are created. x[1]
is replaced by a reference to 1
, not x
/t
itself, and x
is extended to make x[2]
a reference to 2
. (If it helps, think of x[1:] = t
as producing the same result as x = [x[0]]; x.extend(t)
.)