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

Guido van Rossum guido at python.org
Mon Aug 23 22:50:19 CEST 2010


On Mon, Aug 23, 2010 at 1:33 PM, Raymond Hettinger <
raymond.hettinger at gmail.com> wrote:
>
> I don't have a specific proposal in mind.
>

That's why I called it scope creep. :-) Trust me, your proposal will not
lead to a quick and better replacement for hasattr(). (See several other
people's replies.)


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

getattr(obj, 'key', None) returns None when obj.key exists and has the value
None. The workaround is ugly.

* 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. They
call hasattr() because they want to avoid a try/except clause. The reasons
they are not calling getattr(obj, key, None) could be many: never heard of
it, too obscure (it surely doesn't spell "has the attribute" like hasattr()
does to the beginning user), or (probably common) the actual attribute
access is in some other piece of code they are about to call but don't
control.


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

It already raises *some* exceptions (those derived from BaseException but
not Exception). I think that change was a definite non-event.


> 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:
>

But note that hasattr() doesn't call those.

> int PyObject_HasAttr(PyObject <http://structures.html#PyObject>* *o*,
> PyObject <http://structures.html#PyObject>* *attr_name*)<#12aa0a7c7d265b64_PyObject_HasAttr>
> 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<http://structures.html#PyObject>
> * *o*, const char* *attr_name*) <#12aa0a7c7d265b64_PyObject_HasAttrString>
> 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.
>
>
>


-- 
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20100823/b84b221f/attachment.html>


More information about the Python-Dev mailing list