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 ...[1, 2, 3]
aList = [box(1), box(2), box(3)] map(unbox, aList)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@python.org http://mail.python.org/mailman/listinfo/tutor
_______________________________________________ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor