[Python-ideas] Specificity in AttributeError

Devin Jeanpierre jeanpierreda at gmail.com
Sat Apr 27 06:44:16 CEST 2013


Code:
     class A:
        @property
        def text(self):
            return self.foo

Behavior:
    >>> hasattr(A(), 'text')
    False

Actually, this is absolutely correct. "A().y" does not give a result
-- in fact, it raises AttributeError. Behavior wise, this is exactly
what it means for an attribute to not exist.

The problem is that this may disguise other issues in one's code.
Suppose one tries to do "duck-type checking", where a function might
get either an object of type A, or an object of type B. It checks if
the object has a certain attribute that objects of type A have, and
treats it as one or the other as a result. This is ugly, but works,
and even works if someone writes a new type that emulates the API of A
or B.

Real Problem:
    class B(object):
        def __init__(self, x):
            if hasattr(x, 'text'):
                x = x.text
            self.x = x

Because of an error inside the text property, B has classified x as
the wrong type, and this will cause errors later in the execution of
the program that might be hard to diagnose. That is what happens when
mistakes are made. Worse is that the error is silenced, in a manner
similar to how hasattr used to silence things like ValueError.

I would not ask that the semantics of hasattr() be changed. hasattr()
has a specific meaning, and I don't know what happens if it is changed
again. What I would ask is that enough information be added to
AttributeError that I can figure out things for myself. Specifically
an attribute that stores the object for which attribute access failed,
and the attribute (string) for which attribute access failed. This
information is known when AttributeError is instantiated, but it's
used to generate a string description and then thrown out.

I would like to be able to write this function:

def hasattr_lite(obj, attr):
    try:
        getattr(obj, attr)
    except AttributeError as e:
        if e.object is obj and e.attribute is attr:
            return False
        raise
    return True

This would let me do this "duck type checking", but also would reduce
the number of errors hidden in the process. So I would like it if
AttributeError gained those attributes, or some equivalent
functionality.

Does that sound reasonable?

-- Devin



More information about the Python-ideas mailing list