Search code examples
pythonglobaltimeit

How to define globals for this timeit call?


This Python 3.11 script benchmarks function f:

import numpy as np, timeit as ti

def f(a):
  return np.median(a)

a = np.random.rand(10_000)
m = None

fun = f'm = f(a)'
t = 1000 * np.array(ti.repeat(stmt=fun, setup=fun, globals=globals(), number=1, repeat=100))
print(f'{fun}:  {np.amin(t):6.3f}ms  {np.median(t):6.3f}ms  {m}')

I intended to get the result of f(a) stored in m, but the call to ti.repeat doesn't do it. I'm getting:

m = f(a):   0.104ms   0.118ms  None

What do I need to change in order to get that? I tried globals={'f': f, 'a': a, 'm': m} and setup='global m' with the same result.


Solution

  • This is because timeit executes the given string of code in a function so changes made to the namespace affects only the local namespace of the function.

    You can instead explicitly change the global namespace by assigning to the dict returned by the globals function:

    fun = f'globals()["m"] = f(a)'
    

    Alternatively, since f(a) always returns the same value, a more typical and arguably preferred approach would be to simply execute m = f(a) as a regular statement outside of timeit:

    m = f(a)
    fun = 'f(a)'