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

Raymond Hettinger raymond.hettinger at gmail.com
Mon Aug 23 22:33:02 CEST 2010


On Aug 23, 2010, at 1:03 PM, Guido van Rossum wrote:

>> 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.
>> 
>> 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.
>> 
>> 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.
> 
> Hm... That sounds like scope creep to me. Properties are supposed to
> be cheap and idempotent. Trying to figure out whether an attribute
> exists without using __getattr__ is fraught with problems -- as soon
> as a class overrides __getattr__ or __getattribute__ you're hosed
> anyway.

I don't have a specific proposal in mind.  My main questions are

* 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?

* 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.

I know my own uses of hasattr() do not expect any exceptions at all.
It comes up in duck typing support different handling for different 
types of inputs.  If others are using it the same way, I think it is
unlikely that they have unittests to cover the possibility that
hasattr() would ever start raising exceptions.


> I can vouch that the reason hasattr() catches too many exceptions is
> that when I first added it (around 1990, I think :-) I wasn't very
> attuned yet to the problems it could cause.

Fire-up the time machine?


Raymond


P.S.  The current behavior seems to be deeply embedded:

int PyObject_HasAttr(PyObject *o, PyObject *attr_name)
Returns 1 if o has the attribute attr_name, and 0 otherwise. This is equivalent to the Python expression hasattr(o, attr_name). This function always succeeds.
int PyObject_HasAttrString(PyObject *o, const char *attr_name)
Returns 1 if o has the attribute attr_name, and 0 otherwise. This is equivalent to the Python expression hasattr(o, attr_name). This function always succeeds.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20100823/183721a7/attachment.html>


More information about the Python-Dev mailing list