I found a lot of questions regarding decorators and classes, and access to the class instance that is being decorated. As far as I could understand, the decorator generator can not access the object instance because, at that time, no object was yet created.
Nevertheless, it seems that if a decorator uses a class reference (I mean, receives cls), then I am able to access to some class field:
class Foo:
_tags = {}
@classmethod
def _tag(cls, tag_name):
def decorator(func):
def tmp(*args, **kwargs):
return func(*args, **kwargs)
cls._tags[tag_name] = func.__name__
return tmp
return decorator
This works as a charm for subclasses, where I can write:
@Foo._tag("something")
def somethingelse():
pass
But this stores the information in the father class (as expected), as we are talking about class variables.
I wonder if there is a way to have a similar behavior, but guaranteeing that each subclass has its own instance of the _tags property.
I can foresee some workarounds, like parsing the source code, or inspecting the functions, during __init__. But I was looking for a simpler way, if there is such a way.
Edit 1: to make it clearer, I want to decorate methods from the subclass. Thus, this is not a possibility:
Class Bar (Foo):
@Bar._tag("method")
def method(self):
pass
as the processor/compiler did not complete the creation of the class yet. Otherwise, the solution proposed of a two level dictionary with class/method would work good enough for me.
WORKAROUND
My decorator:
@classmethod
def TAG(cls, name):
def decorator(func):
def tmp(*args, **kwargs):
return func(*args, **kwargs)
tmp._has_alias = name
return tmp
return decorator
During __init__, I get this info, and store:
self._tags = {getattr(self, name).has_alias: name for name in dir(self) if callable(getattr(self, name)) and hasattr(getattr(self, name), "_has_alias")}