← Back to Python

__getattr__ vs __getattribute__

PythonSeniorpython

The Question

What is the difference between __getattr__ and __getattribute__?

What a Strong Answer Covers

  • __getattribute__ = every access
  • "__getattr__ = only on failure
  • "object.__getattribute__ escape

Senior-Level Answer

`__getattribute__` and `__getattr__` are both attribute access hooks, but they differ fundamentally in when they are called and how dangerous they are to override.

**`__getattribute__`** is called on *every* attribute access—`obj.x` unconditionally invokes `type(obj).__getattribute__(obj, 'x')`. It's the lowest-level hook in Python's attribute lookup machinery. Overriding it gives you total control over attribute resolution. The danger: any attribute access inside `__getattribute__` itself (including `self.anything`) recursively calls `__getattribute__` again, causing infinite recursion unless you bypass it with `object.__getattribute__(self, name)`. This makes it very easy to write buggy code. Override it only when you need to intercept all attribute access—e.g., read-tracking, transparent proxies, ORM query builders.

**`__getattr__`** is called only when the normal attribute lookup chain fails—i.e., the attribute wasn't found in the instance's `__dict__`, the class, or any base class. It's a fallback hook, not an interception hook. This makes it safe and idiomatic: overriding it adds dynamic attribute behavior without interfering with normal attributes.

Common use cases for `__getattr__`: providing dynamic attributes based on naming conventions (e.g., `obj.get_field_name()` on a dynamic schema), lazy-loading expensive attributes, implementing proxy objects that forward attribute accesses to a wrapped object, and fluent builder patterns.

Example:

```python class DynamicProxy: def __init__(self, target): object.__setattr__(self, '_target', target) # bypass __setattr__ def __getattr__(self, name): # only called if normal lookup fails return getattr(self._target, name) ```

Note: even setting `self._target` in `__init__` must use `object.__setattr__` if you've also overridden `__setattr__`, or you risk infinite recursion.

The lookup order matters: `__getattribute__` → instance `__dict__` → class `__dict__` → base class MRO → `__getattr__`. Raising `AttributeError` inside `__getattribute__` triggers `__getattr__` as a fallback.

What Separates a 2/3 from a 3/3

2/3 — Passing but Incomplete

Correctly states __getattribute__ intercepts all access while __getattr__ is a fallback, explains infinite recursion risk in __getattribute__, gives a use case for __getattr__.

3/3 — Strong Answer

Explains the full attribute lookup order, explains how to safely access self inside __getattribute__ using object.__getattribute__, gives a concrete proxy example, and explains how AttributeError in __getattribute__ triggers __getattr__.

Common Mistakes

  • Saying __getattr__ is called on every access — it's only called when lookup fails
  • Not knowing about infinite recursion risk in __getattribute__ — accessing self.x inside it recurses infinitely
  • Forgetting that object.__getattribute__() is the safe escape hatch inside overrides
  • Mixing up when to use which — __getattr__ is almost always the right choice; __getattribute__ is rarely needed

Follow-Up Questions

  • How do you safely read an instance attribute inside __getattribute__ without infinite recursion? — Use object.__getattribute__(self, name) to bypass the override and go directly to the default implementation.
  • How does __getattr__ interact with __getattribute__? When does __getattr__ get called? — __getattr__ is called when __getattribute__ raises AttributeError — either because the attribute genuinely doesn't exist or because __getattribute__ was overridden to raise it explicitly.
  • Why might you override __getattribute__ in an ORM or proxy framework? — To intercept all attribute accesses for lazy loading, change tracking (mark object dirty on read), or to redirect attribute access to a remote object transparently. The interception must be total, not just for missing attributes.
  • What is the difference between __getattr__ and __getattribute__ for class-level descriptors? — Descriptors (__get__ on class attributes) are invoked by __getattribute__ as part of normal lookup. __getattr__ never sees descriptor-resolved attributes. If you override __getattribute__ and don't handle descriptors, you break them.

Related Questions

  • GIL — What It Is and What It Protects
  • ThreadPoolExecutor & ProcessPoolExecutor
  • Decorators — Under the Hood
  • Generators & yield
  • Context Managers

Can You Explain This Cold?

Reading the answer is step one. Explaining it unprompted — under interview pressure — is what actually matters. Get AI-graded feedback on your answer with follow-up probes on your weak points.

Get Graded — Free Assessment
GrindQuestionsAITechnical interview assessment
TermsPrivacyAbout