On Tue, Aug 24, 2010 at 7:40 AM, Nick Coghlan email@example.com wrote:
Properties are allowed to do whatever the heck they want. That doesn't mean that you have to execute code to determine whether they exist or not.
If you don't want to execute properties, do the lookup on the type, not the instance (obviously, you know the dance you need to do, since you've linked the code where you did it). Having apparently simple query operations like hasattr/getattr/len/etc execute arbitrary code is where much of the language's flexibility comes from, so I don't see how it can really be surprising when it happens.
Now, it may be worth considering an addition to the inspect module that was basically:
def getattr_static(obj, attr): """Retrieve attributes without triggering dynamic lookup via the descriptor protocol, __getattr__ or __getattribute__.
Note: this function may not be able to retrieve all attributes reported by dir(obj) """ try: instance_dict = object.__getattribute__(obj, "__dict__") except AttributeError: pass else: if attr in instance_dict: return instance_dict[attr] for entry in getmro(obj.__class__): try: return entry.__dict__[attr] except AttributeError: pass
(not needing to deal with classic classes simplifies things a bit)
So, allowing for the fact that dir() may report attributes that can only be found via dynamic lookup, your get_docstrings example could become something like:
def get_docstrings(obj): try: members = dir(obj) except Exception: members =  for member in members: try: doc = getattr_static(obj, member).__doc__ except AttributeError: doc = None yield member, doc