Syrtis Major
Syrtis Major

Reputation: 3949

in python what's the relation between the loop variable and the elements in list when we do for loop?

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

Answers (2)

paxdiablo
paxdiablo

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

BrenBarn
BrenBarn

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

Related Questions