'if foo' calls getattr?!?
Joe Strout
joe at strout.net
Mon Aug 30 13:50:23 EDT 1999
[[ This message was both posted and mailed: see
the "To," "Cc," and "Newsgroups" headers for details. ]]
Doing some profiling on Graphite this weekend, we found a very curious
thing: a gazillion calls to __getattr__ on one of our classes, where we
expected to find none. We eventually tracked it down to a seemingly
innocent test, basically, "if foo: self.myfoo = foo". The "if foo" was
invoking foo.__getattr__ (which is very expensive).
I can think of no reason why it should be this way, but it is. Below is
a very simple stand-alone demonstration. It leads me to the absurd
idiom of saying "if id(foo) != id(None)" when I really mean "if foo",
just because using id() avoids the __getattr__ call.
Can anybody explain why this should be? Is it a bug in Python? Is
there some other way to check whether I have a reference to an object
that doesn't involve a function call?
Confused,
-- Joe
getattrcount = 0
class Foo:
def __getattr__(self,attr):
global getattrcount
getattrcount = getattrcount+1
return self.__dict__[attr]
def testA():
global getattrcount
getattrcount = 0
foo = Foo()
for i in range(42):
if foo: pass
print "calls due to 'if foo':", getattrcount
def testB():
global getattrcount
getattrcount = 0
foo = Foo()
for i in range(42):
if id(foo) != id(None): pass
print "calls when using id:", getattrcount
testA() # results in 84 calls!
testB() # results in 0 calls.
--
,------------------------------------------------------------------.
| Joseph J. Strout Biocomputing -- The Salk Institute |
| joe at strout.net http://www.strout.net |
`------------------------------------------------------------------'
Check out the Mac Web Directory! http://www.strout.net/macweb.cgi
More information about the Python-list
mailing list