Why calling assigned lambda is faster than calling function and lambda (not assigned)?

Question:

Why calling an assigned lambda in python3.11 is faster than:

  • calling function
  • lambda that isn’t assigned

Why this happens only (maybe) on python 3.11 and not 3.7?

I tried this:

Python 3.11.2 (tags/v3.11.2:878ead1, Feb  7 2023, 16:38:35) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from timeit import timeit
>>>
>>> def test():
...     return 100 * 1000
...
>>> test2 = lambda: 100 * 1000
>>>
>>> print(timeit("test()", globals=globals()), timeit("test2()", globals=globals()), timeit("lambda: 100 * 1000"))
0.04339419997995719 0.039589399995747954 0.04896240000380203

and this:

Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 16:30:00) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from timeit import timeit
>>>
>>> def test():
...     return 100 * 1000
...
>>> test2 = lambda: 100 * 1000
>>> print(timeit('test()', globals=globals()), timeit('test2()', globals=globals()), timeit('lambda: 100 * 1000'))
0.05223070000000973 0.05272850000000062 0.03326450000000136

I don’t know is it my fault or python interpreter.
Why on python3.11 assigned lambda call is faster that function and unassigned lambda call?
Does this mean that lambdas should be assigned for better performance or is it just an error on python3.11?

Asked By: NotMEE12

||

Answers:

Besides the incorrectness of just defining a lambda and not calling it, as stated in the comments, this test is full of jitter – calling timeit on similar statements on my box get me variations of more than 100% between consecutive calls ,and even more than 30% with 10_000_000 runs (instead of the default 1_000_000 runs).

For the record , the assigned lambda and defined function are the same bytecode and internal-runtime-wise -as you can check by disassembling both:

In [39]: from dis import dis

In [40]: def test():
    ...:     return 1 + 2
    ...: 

In [41]: test2 = lambda: 1 + 2

In [42]: dis(test)
  1           0 RESUME                   0

  2           2 LOAD_CONST               1 (3)
              4 RETURN_VALUE

In [43]: dis(test2)
  1           0 RESUME                   0
              2 LOAD_CONST               1 (3)
              4 RETURN_VALUE
Answered By: jsbueno