There's no such general optimization on CPython, the reference Python implementation. There are a variety of more specific things that could be happening, but we can't tell what.
Marcos's answer suggests it's pyc
file creation, but that's not how timeit
works, even if you call timeit.default_timer
yourself (which you shouldn't - you should be using timeit.timeit
or timeit.repeat
or other such mechanisms).
pyc
files are created when a module is imported that does not have a pyc
file, or whose pyc
file is out of date. They are not created for timeit
snippets, and even if your timed code comes from an imported module, typical timeit
usage patterns will import the module before timing starts.
You're calling timeit.default_timer
instead of letting timeit
handle things the way it's designed to work, but even then, any pyc
file creation is unlikely to happen within the timed code.
PyPy, an alternate Python implementation, uses JIT compilation, but you'd probably know if you were on PyPy.
Numba, a library used to accelerate numeric computation, has its own JIT mechanisms, which could also cause speedup after the first run. It's easier to depend on Numba without noticing than to run on PyPy without noticing.
Memory allocation might happen faster on subsequent runs, depending on what types you're using and details of how they interact with the memory management system, as well as how your malloc
behaves. For example, there might be free lists with more memory blocks on them after the first run.
There are other possibilities, but ultimately, we can't really tell what's happening.