[Python-Dev] 'hasattr' is broken by design

Steven D'Aprano steve at pearwood.info
Tue Aug 24 01:56:27 CEST 2010


On Tue, 24 Aug 2010 06:50:19 am Guido van Rossum wrote:

> > * Is there anything that hasattr(obj, key) can or should do that
> >   can't already be done with getattr(obj, key, None)?
> >   If not, do we really need to change anything?
>
> getattr(obj, 'key', None) returns None when obj.key exists and has
> the value None. The workaround is ugly.

Why do you say it's ugly? It's a short, sweet, simple two-liner:

mark = object()
getattr(obj, 'key', mark) is not mark

Nothing ugly about it at all. But if somebody really objected to using a 
two lines, they could put it in a utility function.

It still doesn't cope with dynamically-generated attributes that are 
either expensive or have side-effects (both of which are probably poor 
design, but nevertheless I'm sure they're out there), but neither does 
the existing hasattr.


> * Why do people typically use hasattr() instead getattr()?
>
> >    Aren't they are really trying to just determine
> >    whether a key exists somewhere in the MRO?
> >    If so, then doing anything more than that is probably a
> > surprise.
>
> Most users who call hasattr() probably don't even know what MRO
> means. 

Well, yes, but most users never write __getattr__ or __getattribute__ 
methods either.

I have always thought that hasattr() does what it says on the box: it 
tests for the *existence* of an attribute, that is, one that statically 
exists rather than being dynamically generated. In other words, it is a 
key in the instance __dict__ or is inherited from the class __dict__ or 
that of a superclass, or a __slot__.

Now that I know that hasattr doesn't do what I thought it does or what 
the name implies it does, it has little or no utility for me. In the 
future, I'll just write a try...except block and catch errors if the 
attribute doesn't exist.



-- 
Steven D'Aprano


More information about the Python-Dev mailing list