[Tutor] References in loops

Jacob S. keridee at jayco.net
Sat Feb 12 03:13:13 CET 2005


Of all the odd quirks of python, this is the only thing that has bitten be 
in the butt.
And several, several times.
List comprehensions have similar limitations as python lambdas, however, so 
I guess the only way to execute several expressions on the item in the list 
would be to pass the item to a function and return the changed item?

Thoughts,
Jacob


> On Fri, 11 Feb 2005, Matt Dimmic wrote:
>
>> In Python, one bug that often bites me is this:
>>
>> (example A)
>> aList = [1,2,3]
>> for i in aList:
>>     i += 1
>> print aList
>> --> [1,2,3]
>>
>> This goes against my intuition, which is that aList == [2,3,4], probably
>> because so much in Python is passed by reference and not by value.
>
>
> Hi Matt,
>
>
> Yes.  If we "unroll" the loop, we can better see what's going on:
>
> ###
> aList = [1, 2, 3]
> i = aList[0]
> i += 1
> i = aList[1]
> i += 1
> i = aList[2]
> i += 1
> print aList
> ###
>
> This has the same meaning as Example A, and it should be clearer why the
> assignment to 'i' has no affect.  'i' is just a regular local variable,
> just like any other local variable.
>
> Assignment is not the same thing as value mutation; it's actually the same
> issue that we talked about earlier with the default argument thread.
> *grin*
>
>
>
> When I see something like:
>
> ###
> x = 42
> y = x
> y = y + 1
> ###
>
>
> My visual model of this is that variable names are "arrows" to values:
>
> --------------------------------------------------
>
>     x -----------> 42            ##  x = 42
>
> ----------------------------------------------------
>
>     x -----------> 42            ## y = x
>                    ^
>                   /
>     y -----------/
>
> ----------------------------------------------------
>
>     x -----------> 42            ## y = y + 1
>
>     y -----------> 43
>
> ----------------------------------------------------
>
>
>
> That being said, we can do something here with a little indirection:
>
> ###
>>>> def box(x):
> ...     """Put a mutable wrapper around the value x."""
> ...     return [x]
> ...
>>>> def unbox(boxedValue):
> ...     """Grab the value in the box."""
> ...     return boxedValue[0]
> ...
>>>> def incr(boxedValue):
> ...     """Increment the value in the box."""
> ...     boxedValue[0] += 1
> ...
>>>>
>>>>
>>>> aList = [box(1), box(2), box(3)]
>>>> map(unbox, aList)
> [1, 2, 3]
>>>> for b in aList:
> ...     incr(b)
> ...
>>>> map(unbox, aList)
> [2, 3, 4]
> ###
>
> This might be overkill, though.  *grin*
>
> But this shows that, if we really needed to, we could "box" everything in
> some kind of mutable container.  I don't recommend this for normal Python
> programming, though.
>
>
>
>> Of course I can always use range() or enumerate():
>>
>> (example B)
>> aList = [1,2,3]
>> for i in range(len(aList)):
>>     aList[i] += 1
>> print aList
>> --> [4,5,6]
>>
>> But example A seems more elegant, if only it did what I wanted it to do.
>> :) So pardon my ignorance if the answer is obvious, but what is the
>> simplest way in Python to get a reference to an element in a list? Is it
>> really Example B?
>
> A variation of Example B, with enumerate(), is probably the most
> straightforward way to do in-place mutation on the list in Python:
>
> ###
> aList = [1, 2, 3]
> for i, x in enumerate(aList):
>    aList[i] = x + 1
> print aList
> ###
>
> There are languages that magically allow us to do mutation on a list
> without making it look like list mutation.  Perl is one of those languages
> that adds magic syntactic sugar for doing in-place list stuff.  But Python
> has no special mechanisms for doing this.
>
>
> The main issue that I think people are running against is that, in Python,
> numeric values are "immutable" --- they can't be changed.  When we do
> things like addition:
>
> ###
>>>> x = 7
>>>> x = x + 1
> ###
>
> we are not changing the value of '7': we're just "re-aiming" or directing
> 'x' to the new value '8'.
>
>
> If you have more questions, please feel free to ask!
>
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
>
> 



More information about the Tutor mailing list