[Tim Peters]
def lookup1(arg, _marker=object()): return _marker ... _marker = object() def lookup3(arg): return _marker ... lookup1 0.427597 lookup3 0.404399
[Dieter Maurer]
Do you understand why "lookup3" is faster than "lookup1"?
I had the "impression" that access to the function's local namespace should be faster than any other variable access.
It is, although module-global lookup is often much faster now than Python old-timers "know" it is <wink>: the critical successful path thru the dict lookup code for a dict keyed by interned strings is, in the absence of collisions, _almost_ as lean as an indexed array access now. The primary difference in speed remaining is that the dict lookup endures an extra C-level function call. I explained a relevant difference last time: lookup1 has the additional expense of initializing an additional local variable. That's what a default argument becomes, and nothing happens for free. Let's time this effect "in isolation": """ from itertools import repeat from time import clock as now def with(default=5): pass def without(): pass for dummy in range(3): for f in with, without: start = now() for dummy in repeat(None, 1000000): f() finish = now() print "%-8s %.6g" % (f.__name__, finish - start) """ and typical output: with 0.374435 without 0.338555 with 0.370469 without 0.339791 with 0.372165 without 0.337355 So adding a default argument indeed has a measurable cost (although ~0.03 seconds across a million calls is nothing to fret about!). Note that the difference between lookup1 and lookup3 was less than that on this box, reflecting that the lookup _inside_ lookup1 goes faster than the lookup inside lookup3, partly cancelling lookup1's higher call overhead; the difference in call overhead is greater than the difference in lookup speed, so lookup1 ends up a net loser.