This question answers how to implement __getattr__
for static/class attributes - using a metaclass. However, I would like to implement __getattr__
and __getattribute__
for a class generated by type()
and to make things even more interesting, the class inherits a class which has a custom metaclass which must be executed properly.
The code summarizing the paragraph above:
class Inherited(metaclass=SomeFancyMetaclass):
...
generated_class = type("GeneratedClass", (Inherited,), {})
def __class_getattr__(cls, name): # __getattr__ for class, not sure how the code shall look exactly like
return getattr(cls, name)
setattr(generated_class, "__getattr__", __class_getattr__) # similarly for __getattribute__
The question: is this possible, and if so, how? Could someone provide a minimal working example?
Just make your metaclass inherit from SomeFancyMetaclass, implement the __getattr__
(and __getattribute__
) there properly, and use this metaclass, rather than a call to type
to generate your inheited, dynamic class.
Although you are using a lot of seldom used stuff, there are no special mechanisms in the way - it should be plain Python -
Of course, you did not tell what you want to do in the metaclass special methods - there might be some black magic to be performed there - and if you are doing __getattribute__
, you always have to be extra careful, and redirect all attrbiutes that you don't care about to the super-call, otherwise, nothing works.
Also, keep in mind that the attribute-access ustomization possible with both methods won't work to "create magic dunder methods" - that is: your class won't magically have an __add__
or __dir__
method because your metaclass __getattribute__
generates one - rather, these are fixed in spcial slots by the Python runtime, and their checking and calling bypasses normal attribute lookup in Python.
Otherwise:
class Inherited(metaclass=SomeFancyMetaclass):
...
class MagicAttrsMeta(Inherited.__class__):
def __getattr__(self, attr):
if attr in ("flying", "circus", "brian", "king_arthur"):
return "coconut"
raise AttributeError()
generated_class = MagicAttrsMeta("GeneratedClass", (Inherited,), {})