2010/8/23 Raymond Hettinger firstname.lastname@example.org:
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.)