[Paul Winkler]
But of course we don't do it because accessing globals in a method that might be looped over is slow. Which, hopefully, will become a non-issue some day (PEP 267, 268, 280).
[Jim Fulton]
Note that in my version above, marker is a local rather than a global and gets looked up at local-variable speed.
Nope, it's a "cell" reference to an enclosing scope, and gets looked up at cell-dereference speed. In my experience, that's generally a bit slower than accessing a module global. That may have to do with a quirk of MSVC's code generation; unsure. Here's a little program that times it 3 ways: """ def lookup1(arg, _marker=object()): return _marker def lookup2(): _marker = object() def lookup2(arg): return _marker return lookup2 lookup2 = lookup2() _marker = object() def lookup3(arg): return _marker from time import clock as now # s/clock/time/ on Linux from itertools import repeat for f in lookup1, lookup2, lookup3: start = now() for dummy in repeat(None, 1000000): f(dummy) finish = now() print "%-8s %.6g" % (f.__name__, finish - start) """ Under WinXP Python 2.4.1, the global trick (lookup3) is consistently fastest, and the lexical scope trick (lookup2) is consistently slowest; this is typical output across 3 runs: lookup1 0.427597 lookup2 0.450777 lookup3 0.404399 lookup1 0.423195 lookup2 0.471619 lookup3 0.405306 lookup1 0.42321 lookup2 0.448071 lookup3 0.405078 Note that lookup1 has the overhead of installing the default arg into the locals on each call, which is an expense neither lookup1 nor lookup3 endure. measurement-never-agrees-with-anyone<wink>-ly y'rs - tim