'if foo' calls getattr?!?
Gordon McMillan
gmcm at hypernet.com
Mon Aug 30 15:21:25 EDT 1999
Joe Strout wrote:
> 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.
>
> 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?
>
> 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
If you read the Timbot's posts, you'd know it's not the __getattr__,
it's the "42"!
More instructive is to see what "attr" is: First it's __nonzero__,
and then it's __len__. Python is doing whatever it can to determine
whether your object considers itself "true" or not. Which leads to
the conclusion that "if X" doesn't test if X exists, but whether X is
"true" according to some interpretation.
You've found one solution. You don't say what the alternative to foo
is; if that alternative is non-existance, you've got a NameError. So
I'll assume the alternative is None.
In which case "if foo is not None" will be the fastest and
closest-to-your-intention test possible. (But "if foo != None" will
get you right back to where you are now!).
- Gordon
More information about the Python-list
mailing list