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

Benjamin Peterson benjamin at python.org
Mon Aug 23 21:59:13 CEST 2010


2010/8/23 Raymond Hettinger <raymond.hettinger at gmail.com>:
> Thanks for the nice analysis and good example.
>
> I disagree with the solution though.  If we want to see the exceptions associated
> with actually getting an attribute, then using getattr() instead is a perfectly
> reasonable solution that people can already use without a language change.
>
> But hasattr() has a far different set of use cases, so we should explore
> an alternate solution to the problem.  The usual reason that people use
> hasattr() instead of getattr() is that they want to check for the presence of
> of a method/attribute without actually running it, binding it, or triggering
> any other behavior.

That would break the assumption that:
if hasattr(obj, attr):
     getattr(obj, attr) # won't raise

and hasattr ~=
try:
    getattr(obj, attr)
except AttributeError:
    return False
else:
    return True

>
> As your example shows, property() defeats this intent by actually executing
> the code.   A better behavior would not run the code at all.  It would check
> the dictionaries along the MRO but not execute any descriptors associated
> with a given key.

That doesn't sound to useful to me. A descriptor could be found with
__get__, but that __get__ could just as well raise AttributeError.

>
> IMO, this is a much better solution, more in line with known use cases
> for hasattr().   If the proposed change when through, it would fail to
> address the common use case and cause people to start writing their
> own versions of hasattr() that just scan but do not run code.

Can you provide an example? I've never seen code which explicitly
scans MRO and dicts to avoid triggering code. (Besides
collections.Callable; that's a special case.)



-- 
Regards,
Benjamin


More information about the Python-Dev mailing list