I am trying to estimate the time for running an algorithm by timeit
module. But I ran into a problem when passing the stmt
argument with f-string
. To demonstrate my problems, I create two simple functions to return Fibonacci number as an example:
def fibo_exponential(n):
if n == 0:
return 0
elif n == 1:
return 1
return fibo(n-1) + fibo(n-2)
def fibo_linear(n):
List = [0]*3
List[0] = 0
List[1] = 1
for i in range(2,n+1):
List[2] = List[1] + List[0]
List[0] = List[1]
List[1] = List[2]
return List[2]
from timeit import timeit
def time():
print(timeit('fibo_linear(10)', 'from __main__ import fibo_linear', number=100000))
print(timeit('fibo_exponential(10)', 'from __main__ import fibo_exponential', number=100000))
print(timeit(f"{fibo_linear(10)}", 'from __main__ import fibo_linear', number=100000))
print(timeit(f"{fibo_exponential(10)}", 'from __main__ import fibo_linear', number=100000))
The result is shown below:
time() # The argument for stmt list below:
0.21902308000426274 # 'fibo_linear(10)'
2.1373995500034653 # 'fibo_exponential(10)'
0.0006944179913261905 # f"{fibo_linear(10)}"
0.0006128590030129999 # f"{fibo_exponential(10)}"
My question is that why is time different when using f-string format?
timeit
takes the string that it's given, and evaluates it as python code.
Note that f-strings are evaluated immediately. When you do
f'{fibo_linear(10)}'
and fibo_linear(10)
would resolve to, say, 55, then the string resolves to '55'
.
So, in your first two examples, you're telling timeit
to evaluate the following lines, as python code:
'fibo_linear(10)'
'fibo_exponential(10)'
but in your second two examples, you're telling it to evaluate this:
'55'
which, of course, is nearly instantaneous. Because it's, y'know, a constant.
In other words, f'{fibo_linear(10)}' == '55'
is True
.