Steve D'Aprano wrote:
When you say:x = 0 x = 1 inside a function, and the interpreter does the name binding twice, there's no way of telling whether it writes to the same cell each time or not.
Yes, there is: ... x = 0 ... f1 = lambda: x ... x = 1 ... f2 = lambda: x ... print(f1(), f2()) ... >>> f() 1 1 This indicates that both assignments updated the same slot. Otherwise the result would have been "0 1". It's not currently possible to observe the other behaviour in Python, because the only way to create new bindings for local names is to enter a function. The change to for-loop semantics I'm talking about would introduce another way.
Certainly when you call a function, the local bindings need to be created. Obviously they didn't exist prior to calling the function! I didn't think that was the difference you were referring to, and I fail to see how it could be relevant to the question of for-loop behaviour.
My proposed change is (mostly) equivalent to turning the loop body into a thunk and passing the loop variable in as a parameter. This is the way for-loops or their equivalent are actually implemented in Scheme, Ruby, Smalltalk and many other similar languages, which is why they don't have the same "gotcha". (Incidentally, this is why some people describe Python's behaviour here as "broken". They ask -- it works perfectly well in these other languages, why is Python different?) The trick with cells is a way to get the same effect in CPython, without the overhead of an actual function call on each iteration (and avoiding some of the other problems that using a thunk would entail). The cell trick isn't strictly necessary, though -- other Python implementations could use a thunk if they had to. -- Greg -- https://mail.python.org/mailman/listinfo/python-list
