How do I override __getattr__ in Python without breaking the default behavior?
Overriding __getattr__
should be fine -- __getattr__
is only called as a last resort i.e. if there are no attributes in the instance that match the name. For instance, if you access foo.bar
, then __getattr__
will only be called if foo
has no attribute called bar
. If the attribute is one you don't want to handle, raise AttributeError
:
class Foo(object): def __getattr__(self, name): if some_predicate(name): # ... else: # Default behaviour raise AttributeError
However, unlike __getattr__
, __getattribute__
will be called first (only works for new style classes i.e. those that inherit from object). In this case, you can preserve default behaviour like so:
class Foo(object): def __getattribute__(self, name): if some_predicate(name): # ... else: # Default behaviour return object.__getattribute__(self, name)
class A(object): def __init__(self): self.a = 42 def __getattr__(self, attr): if attr in ["b", "c"]: return 42 raise AttributeError("%r object has no attribute %r" % (self.__class__.__name__, attr))
>>> a = A()>>> a.a42>>> a.b42>>> a.missingTraceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 8, in __getattr__AttributeError: 'A' object has no attribute 'missing'>>> hasattr(a, "b")True>>> hasattr(a, "missing")False
To extend Michael answer, if you want to maintain the default behavior using __getattr__
, you can do it like so:
class Foo(object): def __getattr__(self, name): if name == 'something': return 42 # Default behaviour return self.__getattribute__(name)
Now the exception message is more descriptive:
>>> foo.something42>>> foo.errorTraceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 5, in __getattr__AttributeError: 'Foo' object has no attribute 'error'