How python attribute lookup process works?
If you added print("Metaclass getattribute invoked:", self, name)
you'd see:
>>> c.__getattribute__Class getattribute invoked: <__main__.C object at 0x2acdbb1430d0> __getattribute__Metaclass getattribute invoked: <class '__main__.C'> __name__<bound method C.__getattribute__ of <__main__.C object at 0x2acdbb1430d0>>
The metaclass __getattribute__
is getting invoked in order to build the repr
of the expression c.__getattribute__
, so that it can print C
's __name__
.
btw, __getattribute__
works the same for classes and metaclasses; the attribute is looked up first on the instance then on the instance's type.
>>> Meta.foo = 1>>> C.foo('Metaclass getattribute invoked:', <class '__main__.C'>, 'foo')1>>> c.foo('Class getattribute invoked:', <__main__.C object at 0x2acdbb1430d0>, 'foo')Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 5, in __getattribute__AttributeError: 'C' object has no attribute 'foo'>>> C.bar = 2>>> c.bar('Class getattribute invoked:', <__main__.C object at 0x2acdbb1430d0>, 'bar')2