For a class Foo
,
class Foo:
...
is there a way to call a specific method whenever Foo.XXX
(an arbitrary class attribute XXX
, such as bar
, bar2
, etc.) is being resolved, but NOT whenever Foo().XXX
(an arbitrary instance attribute) is resolved? To the best of my knowledge, overriding
def __getattr__(self, a):
...
applies to the second case only. I'd like to benefit from the fact that __getattr__
for instances is called only when the corresponding attribute is not found. Does anyone know how this should be solved? I've read through the manual and found nothing of relevance.
I don't particularly care what happens if someone tries to assign a value to any class or instance attribute of Foo
.
Class Foo
is a messenger. Instances of Foo
are basically tuples with extra steps. However, there are special cases of Foo
, which I'd like to store as class attributes of Foo
(I managed that using a special decorator). However, the number of special cases of Foo
is gradually growing while they differ very insignificantly. It would be very efficient code-wise for me to have this special function called whenever someone wants Foo.SPECIAL_CASE_123
, because mapping from "SPECIAL_CASE_123"
to the actual special case is very fast and very similar to mapping "SPECIAL_CASE_456"
to the other corresponding special case.
Use a metaclass to define how classes behave. In specific, redefine the class' __getattr__
to change how attributes missing on the class are handled:
# The "Type of Foo"
class MetaFoo(type):
def __getattr__(cls, item):
return f"Dynamically handled: {item}"
class Foo(metaclass=MetaFoo):
REGULAR_CASE_22 = "Catch 22"
print(Foo.REGULAR_CASE_22) # Catch 22
print(Foo.SPECIAL_CASE_123) # Dynamically handled: SPECIAL_CASE_123
print(Foo().REGULAR_CASE_22) # Catch 22
print(Foo().SPECIAL_CASE_123) # AttributeError: 'Foo' object has no attribute 'SPECIAL_CASE_123'
Note that certain attribute lookups, such as for special methods like __add__
, will circumvent the metaclass attribute lookup.