Question presented to candidate:
"Python classes can define both __getattr__ and __getattribute__. What is the difference, when does each one run, and which would you use to build something like a proxy or a lazy-loading object?"
What a strong answer should cover:
__getattribute__is called for every attribute read on an instance (including methods and__dict__);object.__getattribute__implements the normal lookup.__getattr__is a fallback, called only when the normal lookup raisesAttributeError; the normal case pays nothing for it.- The recursion trap: any
self.xinside__getattribute__calls it again; useobject.__getattribute__(self, name)orsuper().__getattribute__(name). - Both must raise
AttributeErrorfor unknown names sohasattrandgetattr(obj, name, default)keep working; anAttributeErrorescaping a property silently triggers__getattr__. - Implicit special-method lookups (
len(x),x + y) bypass both on the instance, so a proxy must define the dunders it needs; modules can define__getattr__too (PEP 562, Python 3.7). - Choice:
__getattr__for delegation, defaults and lazy attributes;__getattribute__only for rare cases that must see every access (tracing, access control), because it is slower and easy to get wrong.
Code / implementation expected: Optional β a delegating proxy with __getattr__, or a tracing __getattribute__ that calls object.__getattribute__.