You are invited to Log in or Register a free Frihost Account!

# [pyhon] function in function --- strange things

rocking
I executed the code:

z = {}
for x in range(10):
def y():
print x
z[x] = y

this is what I got:

>>> z
{0: <function y at 0xdc4b90>, 1: <function y at 0xe372a8>, 2: <function y at 0xe37320>, 3: <function y at 0xe37398>, 4: <function y at 0xe37410>, 5: <function y at 0xe37488>, 6: <function y at 0xe37500>, 7: <function y at 0xe37578>, 8: <function y at 0xe375f0>, 9: <function y at 0xe37668>}

>>> z[0]
<function y at 0xdc4b90>

>>> z[0]()
9
>>> z[1]()
9

-------------------------------------
This very strange I expected to get 9 nine others functions, that everyone prints other number.
I could understand what happend if I got only 1 function.
But in this case I see 9 other functions (that acts the same?), I can see that this is not same function,
because when I printed the dict (As you see above) I see the function stored in different locations in memory.

jcreus
 rocking wrote: I executed the code: z = {} for x in range(10): def y(): print x z[x] = y this is what I got: >>> z {0: , 1: , 2: , 3: , 4: , 5: , 6: , 7: , 8: , 9: } >>> z[0] >>> z[0]() 9 >>> z[1]() 9 ------------------------------------- This very strange I expected to get 9 nine others functions, that everyone prints other number. I could understand what happend if I got only 1 function. But in this case I see 9 other functions (that acts the same?), I can see that this is not same function, because when I printed the dict (As you see above) I see the function stored in different locations in memory. please help!

What I understand is that x becomes a global variable, and, as such, is available at all time, in all functions. So, you assign each value in range 0-10 a function, which returns the value of x. Since you call all those functions after the loop has ended, the result is always 9.

However, if the function is always the same, you could do something like:
 Code: arr = range(10) y(arr[0])

or whatever.

Hope it helps.
clubdeinovaristi
jcreus wrote:

However, if the function is always the same, you could do something like:
 Code: arr = range(10) y(arr[0])

Another approach could be:
 Code: def return_lambda(y):     return lambda: y z = {} for x in range(0,10):     z[x] = return_lambda(x)

x is keeped in the return_lambda function context.
angj888
z = {}
for x in range(10):
def y(x=x):
print x
z[x] = y

this will make it work.
z[0]() => 0
z[8]() => 8
lucascoelho
 angj888 wrote: z = {} for x in range(10): def y(x=x): print x z[x] = y this will make it work. z[0]() => 0 z[8]() => 8

God, Python is really awesome!! I was freaking out about the "x=x" until I made some tests and realized the first one is in the definition of the inside function, while the other one is just the iterator in the range.
I mean, it's probably not even just a "Python-stuff", but in a simpler syntax like it has it's even more amazing those tricks!
Fire Boar
x shouldn't become a global variable, though in Python it might. However, if we consider scope to have meaning, the behaviour you are noticing should still occur. The variable x is within the scope of y, so because all y are added to z, x is still active, even though the loop in which it was defined has terminated. By the end of the loop, x is only accessible through any of the y in z. You've effectively got a read-only variable. This is a common trick in Javascript, which does have scope but also has no inherent concept of encapsulation and safety.
shazhouke
lucascoelho wrote:
 angj888 wrote: z = {} for x in range(10): def y(x=x): print x z[x] = y this will make it work. z[0]() => 0 z[8]() => 8

God, Python is really awesome!! I was freaking out about the "x=x" until I made some tests and realized the first one is in the definition of the inside function, while the other one is just the iterator in the range.
I mean, it's probably not even just a "Python-stuff", but in a simpler syntax like it has it's even more amazing those tricks!

It works because the default values of the arguments are calculated immediately as you define the function. The argument x inside function y is a different object than the x outside, so it never changes as the loop var x grows.
However, it's not recommended to write program like this. You'd better not to use the same var name. It may get people confused.
Related topics