+ 3

Why do these two functions perform equally well?

I have played around a bit: from timeit import timeit x = 1 def f(n=500): if not n: return x f(n-1) def h(x, n=500): if not n: return x h(x, n-1) def g(): h(1) print(timeit(f, number=10000)) print(timeit(g, number=10000)) One function accesses the value x from global, the other takes it as an argument. Both functions go deep into recursion. I wanted to see if there is a loss of performance, if each call has to scramble down the call stack to fetch x from the globals, or how much of a difference it would make. Funnily there doesn't seem to be one: Over several attempts, both functions performed about equally well. Can someone explain how this is possible?

2nd Mar 2020, 12:00 AM
HonFu
HonFu - avatar
11 Answers
+ 5
HonFu it appears there is a loss between them and depending on what this might be for that can be significant https://code.sololearn.com/co434SthupBB/?ref=app
2nd Mar 2020, 12:16 AM
BroFar
BroFar - avatar
+ 3
Namespace scopes are determined textually, not by call stack. Also Python "optimizes" namespaces at compile time: x=1 def f(): exec('x=2') y=3 return (x, y), eval ('(x, y)'), (locals()['x'], locals()['y']) print(f()) will output ((1, 3), (2, 3), (2, 3)) the x from the first tuple has "optimized" namespace and is searched only in globals and builtins (as it is not "known" local and there are no nonlocals), in spite of it was defined in exec() at runtime. The same in your code: x in f() is searched in globals and then in builtins (but not in locals) x in h() is not searched anywhere since known at compile time locals are stored in array and are accessed by indexes. So x in f() has small overhead on search in a dictionary against access to array by index for x in h(). From other side h() has small overhead because of extra parameter. The second one should be bigger, but both overheads are too small to compare It is my understanding of Python's name resolution. If I wrong, please, correct me.
20th Mar 2020, 9:36 PM
andriy kan
andriy kan - avatar
+ 2
BroFar, when I run the code, I get very different results, some positive, some negative. Doesn't this mean that they perform about equally well?
2nd Mar 2020, 12:31 AM
HonFu
HonFu - avatar
+ 2
No not really as they shows unstable and that z for the most part will be faster or finer and integrity less depending on the alloy if metal or say splitting a particles As to y that also shows unstable but might be better.
2nd Mar 2020, 12:38 AM
BroFar
BroFar - avatar
+ 2
andriy kan, that's some serious Py Fu you're showing here! I have to read up on this... *scratches head*
20th Mar 2020, 11:06 PM
HonFu
HonFu - avatar
+ 1
~ swim ~, I thought the search order was local, *nonlocal*, global etc. Wouldn't that entail walking down the complete recursion stack?
2nd Mar 2020, 1:28 AM
HonFu
HonFu - avatar
+ 1
My question had these been separate codes ran at the exact same time what would the difference actually be? Seeing they are sharing the same playground the comparison would be a slight handoff... If my logic is correct. And the data spread out over say a loop of 100
2nd Mar 2020, 2:06 AM
BroFar
BroFar - avatar