
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.