Decorate a class in Python by defining the decorator as a class
27,862
Solution 1
If you want to overwrite new_method()
, just do it:
class Decorator(object):
def __init__(self, arg):
self.arg = arg
def __call__(self, cls):
class Wrapped(cls):
classattr = self.arg
def new_method(self, value):
return value * 2
return Wrapped
@Decorator("decorated class")
class TestClass(object):
def new_method(self, value):
return value * 3
If you don't want to alter __init__()
, you don't need to overwrite it.
Solution 2
After this, the class NormalClass becomes a ClassWrapper instance:
def decorator(decor_arg):
class ClassWrapper:
def __init__(self, cls):
self.other_class = cls
def __call__(self,*cls_ars):
other = self.other_class(*cls_ars)
other.field += decor_arg
return other
return ClassWrapper
@decorator(" is now decorated.")
class NormalClass:
def __init__(self, name):
self.field = name
def __repr__(self):
return str(self.field)
Test:
if __name__ == "__main__":
A = NormalClass('A');
B = NormalClass('B');
print A
print B
print NormalClass.__class__
Output:
A is now decorated. <br>
B is now decorated. <br>
\__main__.classWrapper
Related videos on Youtube
Author by
tsps
Updated on January 04, 2020Comments
-
tsps over 4 years
What is a simple example of decorating a class by defining the decorator as a class?
I'm trying to achieve what has been implemented in Python 2.6 using PEP 3129 except using classes not functions as Bruce Eckel explains here.
The following works:
class Decorator(object): def __init__(self, arg): self.arg = arg def __call__(self, cls): def wrappedClass(*args): return cls(*args) return type("TestClass", (cls,), dict(newMethod=self.newMethod, classattr=self.arg)) def newMethod(self, value): return value * 2 @Decorator("decorated class") class TestClass(object): def __init__(self): self.name = "TestClass" print "init %s"%self.name def TestMethodInTestClass(self): print "test method in test class" def newMethod(self, value): return value * 3
Except, in the above, wrappedClass is not a class, but a function manipulated to return a class type. I would like to write the same callable as follows:
def __call__(self, cls): class wrappedClass(cls): def __init__(self): ... some code here ... return wrappedClass
How would this be done?
I'm not entirely sure what goes into """... some code here ..."""
-
Sven Marnach over 12 yearsDid you try the code you posted yourself? It should work.
-
tsps over 12 yearsThe first part using the function does work. How would I write wrappedClass as a genuine class though?
-
Sven Marnach over 12 yearsWhat is your decorator supposed to do? I cannot tell you what code has to go into "some code here" without knowing what this code is supposed to do.
-
tsps over 12 yearsI want to achieve what can be achieved with a function using a class. I understand this can be done, but couldn't find any examples to illustrate this
-
Sven Marnach over 12 yearsI don't get it. The code in your second snippet should work as it is. You can put just any code where "some code here" is. How am I supposed to now what this code is supposed to do? If you don't want to overwrite
__init__()
, simply don't. If you do want to overwrite it, you obviously want to change its behaviour in some way. I'm asking: In what way? -
tsps over 12 yearsThe decorator should alter the method "newMethod" in TestClass which triples values to a method that just doubles values. In other words it has to replace the method in TestClass. I get my panties in a bunch soon after I declare __init__(self) and get confused by the Decorator's reference to itself, the class (cls) I am decorating and the wrappedClass's self. HTH clear the confusion
-
-
Melvic Ybanez over 9 yearsyou forgot to return the 'other' variable inside the call method
-
han shih almost 4 yearsIs there any scenario that we should decorate class instead of using class inheritance?