'if foo' calls getattr?!?

Ted Horst Ted.Horst at wdr.com
Mon Aug 30 20:07:41 CEST 1999


On Mon, 30 Aug 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.  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

The statement

if foo:

tries to determine the truth value of foo.  Different types respond to this  
differently.  An instance will respond by returning the results of  
__nonzero__ if defined, or else returning the result of __len__ if defined.

The following session illustrates this, and a faster way to check for None.

>>> class Foo:
...     def __getattr__(self,name):
...             print name
...             raise AttributeError, name
...
>>> foo = Foo()
>>> if foo:
...     print 'yes'
...
__nonzero__
__len__
yes
>>> if foo is not None:
...     print 'yes'
...
yes
>>>

Ted

---




More information about the Python-list mailing list