3

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 :)

Syrtis Major
  • 3,791
  • 1
  • 30
  • 40

2 Answers2

7

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.

Community
  • 1
  • 1
BrenBarn
  • 242,874
  • 37
  • 412
  • 384
  • See this [related answer](http://stackoverflow.com/a/2022044/1988505) explaining more about creating a new list by adding to it vs. inserting into an original list. – Wesley Baugh Mar 12 '13 at 06:07
  • Thanks a lot for your answer, it's much clearer for me now. It seems that I should learn more basics about python:) – Syrtis Major Mar 12 '13 at 06:32
3

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.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • You are right, names and objects are different. Names are like *labels* put on an object; assigning a label to an object is done through `name = …` (this is called binding the object to the name). An single object can have many labels (like when doing `name2 = name`). A difficulty is that `name` represents a label, in `name = …`, but an *object* in `name2 = name` (or `name += [0]`). – Eric O. Lebigot Mar 12 '13 at 06:50
  • So list are similar to array in C, we can use the slice to change the value. Ah, I find an other solution, for x in [a, b]: x[:] = x + [0], python is intersting. – Syrtis Major Mar 12 '13 at 06:51