Asked By – Robert Gowland
How do I create a decorator that applies to classes?
Specifically, I want to use a decorator
addID to add a member
__id to a class, and change the constructor
__init__ to take an
id argument for that member.
def getId(self): return self.__id classdecorator addID(cls): def __init__(self, id, *args, **kws): self.__id = id self.getId = getId cls.__init__(self, *args, **kws) @addID class Foo: def __init__(self, value1): self.value1 = value1
The above should be equivalent to:
class Foo: def __init__(self, id, value1): self.__id = id self.value1 = value1 def getId(self): return self.__id
Now we will see solution for issue: How to decorate a class?
I would second the notion that you may wish to consider a subclass instead of the approach you’ve outlined. However, not knowing your specific scenario, YMMV 🙂
What you’re thinking of is a metaclass. The
__new__ function in a metaclass is passed the full proposed definition of the class, which it can then rewrite before the class is created. You can, at that time, sub out the constructor for a new one.
def substitute_init(self, id, *args, **kwargs): pass class FooMeta(type): def __new__(cls, name, bases, attrs): attrs['__init__'] = substitute_init return super(FooMeta, cls).__new__(cls, name, bases, attrs) class Foo(object): __metaclass__ = FooMeta def __init__(self, value1): pass
Replacing the constructor is perhaps a bit dramatic, but the language does provide support for this kind of deep introspection and dynamic modification.