[Zope-dev] Re: hasattr implementation for Zope?

Tim Peters tim.peters at gmail.com
Fri May 27 13:49:00 EDT 2005


[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


More information about the Zope-Dev mailing list