12

How can I override class attribute access in python?

P.S. Is there a way to leave regular access to class attributes alone but calling a more specific exception on missing attribute?

Roman A. Taycher
  • 18,619
  • 19
  • 86
  • 141

2 Answers2

23

The __getattr__ magic method is called when the attribute doesn't exist on the instance / class / parent classes. You'd use it to raise a special exception for a missing attribute:

class Foo:
    def __getattr__(self, attr):
        # only called when self.attr doesn't exist
        raise MyCustonException(attr)

If you want to customize access to class attributes, you need to define __getattr__ on the metaclass / type:

class BooType(type):
    def __getattr__(self, attr):
        print attr
        return attr

class Boo(metaclass=BooType):
    pass

boo = Boo()
Boo.asd # prints asd
boo.asd # raises an AttributeError like normal

If you want to customize all attribute access, use the __getattribute__ magic method.

agf
  • 171,228
  • 44
  • 289
  • 238
  • 2
    Doesn't that modify instance not class attribute access? – Roman A. Taycher Mar 22 '12 at 10:26
  • "If you want to customize all attribute access, use the __getattribute__ magic method." is misleading: to quote a comment from another question: "__getattribute__ is only invoked on instance attribute access - if you want it invoked on class attribute access, it needs to be on the meta-class." – run_the_race Mar 23 '22 at 20:59
  • As @run_the_race said. See https://docs.python.org/3/reference/datamodel.html#object.__getattribute__ – Sarah Messer Mar 23 '22 at 21:01
  • Note: `class Boo(object):` Code does not work with Python3, use `class Boo(metaclass=BooType): pass` – run_the_race Mar 23 '22 at 21:14
  • @agf Would you please clarify what you mean by "all attrbiute access" ? (since it does not work for static attributes) – run_the_race Mar 25 '22 at 17:01
  • @run_the_race Can you show an example? It sounds like you're describing the class attribute access scenario, where you need to define it on the type. – agf Mar 26 '22 at 18:08
2

agf's answer is correct, and in fact the answer I'm about to give is based on it and owes it some credit.

Just to give more detail on the class-attribute side, which is the part that's actually under question here (as opposed to the difference between __getattr__ and __getattribute__), I'd like to add a reference to an answer I wrote to a different similar question, which goes into more detail on the difference between class and instance attributes, how this is implemented, and why you need to use a metaclass to influence class attribute lookup.

Community
  • 1
  • 1
metamatt
  • 13,809
  • 7
  • 46
  • 56
  • 4
    Hey, your answer to the other question is nice, but this isn't really an answer to this question. You should either add some content here or post this as a comment on the question or my answer. – agf Apr 24 '13 at 15:04