Reputation: 3949
Here are several list: a, b, etc I want to make some change of them respectively, but I'm confused with the behavier of for loop.
for example: if we do
a, b = range(5), range(5,10)
for x in [a, b]: x += [0]
print(a,b)
we get
([0, 1, 2, 3, 4, 0], [5, 6, 7, 8, 9, 0])
a,b are modified.
but if we do
a, b = range(5), range(5,10)
for x in [a, b]: x = x + [0]
print(a,b)
we get
([0, 1, 2, 3, 4], [5, 6, 7, 8, 9])
a,b aren't modified. I'm confused, what's the relation between x and a? When or how I can modify the value of a with x? And by the way, what's the difference between a+=b and a=a+b?
Anyway, I find a solution that we can do like this
a, b = range(5), range(5,10)
lis = [a, b]
for i, x in enumerate(lis):
lis[i] = ...
then we can modify values of a & b. But this method need make a extra list.
And there's anther solution
for x in ['a', 'b']:
exec(x + '=' + x + '+ ...')
And an easier solution
a, b = range(5), range(5,10)
for x in [a, b]: x[:] = x + [0]
print(a,b)
We will find a,b are modified :)
Upvotes: 3
Views: 128
Reputation: 882686
The line:
x += something
changes a list in place, while:
x = x + something
creates a brand new list by joining x
and something
.
It's no different to the following simplified demonstration:
>>> a = [7] # The object is [7], name a is connected to it.
>>> x = a # Now name x is also connected.
>>> x += [2] # Here we change the backing object (behind a AND x).
>>> a # So that both names seem to change.
[7, 2]
>>> x
[7, 2]
>>> a = [7] # The object is [7], name a is connected to it.
>>> x = a # Now name x is also connected.
>>> x = x + [2] # Here we create a NEW object from the old one, and connect x.
>>> a # So a is unchanged.
[7]
>>> x # But x IS changed.
[7, 2]
This was the hardest thing I had to get used to in Python, the fact that names and the objects that names refer to are quite disparate, and can often act in surprising ways. It's also one of its most beautiful features once you nut it out.
I eventually just started thinking that names were C pointers and all objects were on the heap (since that was where I have my expertise). There may be better ways to think of it, though I've never found any for me.
Upvotes: 3
Reputation: 251598
The relation is the same as with all variable binding in Python. The name is bound to the value. The differences you are seeing are because you are doing different things, sometimes, operating on the value and sometimes on the name.
For lists, +=
extends the list in-place --- that is, it modifies the original list. Thus the modifications are visible everywhere that list is used.
When you do x = x + [0]
, you rebind the name x
to a new list (formed by adding the old list plus [0]
). This does not modify the original list, so other places that use that list will not see the change.
If you search around for Python questions on "variables", "names", "values", "call by refernce" and the like you will find other discussions of this. Here is a question discussing a similar issue in the context of function-parameter binding. The principles are the same in for-loop variable binding.
Upvotes: 7