On Mon, Aug 23, 2010 at 1:33 PM, Raymond Hettinger
<raymond.hettinger@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 *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.