On 2010-08-23, at 3:47 PM, Raymond Hettinger wrote: > > On Aug 23, 2010, at 7:22 AM, Yury Selivanov wrote: > >> I know the issue has been discussed several times already, however I >> couldn't find any reasonable explanation of its strange behaviour. The main >> problem with 'hasattr' function is that is swallows all exceptions derived >> from Exception class. It's a good thing that it doesn't do that with >> BaseException as it was fixed not a long time ago, but it's definitely not >> enough. >> >> First of all, this behaviour of 'hasattr' contradicts with the very core >> principle of python: "Errors should never pass silently." And since >> 'hasattr' function is in builtins module and is a widely used function it >> impacts the whole language. >> >> Secondly, take a look at the following: >> >>>>> class Test: >> ... @property >> ... def attr(self): >> ... self['foo'] >> ... >>>>> hasattr(Test(), 'attr') >> False >> >> There can be any exception instead of KeyError in the above snippet of code, >> but this small example shows how 'hasattr': misleadingly breaks the code >> logic (1) and masks bug (2). And that's the simplest possible example, >> there are much more in real life. >> >> While (1) is maybe acceptable for someone, there is no excuse for the (2). >> Moreover, current 'hasattr' behaviour tremendously complicates use of >> '__getattribute__' magic. And forget about importlib magic with >> LazyImports, one 'hasattr' ruins everything by catching ImportError. >> >> >> To conclude: >> >> 1) I propose to change 'hasattr' behaviour in Python 3, making it to swallow >> only AttributeError exceptions (exactly like 'getattr'). Probably, Python >> 3.2 release is our last chance. >> >> 2) If you afraid that this new behaviour will break too much python 2 code >> converted with 2to3, we can introduce another 'hasattr' function defined in >> 2to3 module itself, and make it imported automatically in all files passed >> through 2to3 transformation pipeline. This new function will mimic >> 'hasattr' behaviour from python 2 and converted code should work as expected. > > > 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. > > 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.
This is impossible to implement because of '__getattribute__' and '__getattr__' methods. There is no way of detecting the presence of an attribute but trying to get it through 'getattr'. Partial solution like getting information about property presence through __dict__ and call __getattribute__/__getattr__ if they are defined wouldn't work either. So, your solution would make 'hasattr' even more incompatible. - Yury Selivanov _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com