I am trying to create a decorator that will inject some functionality to wrapped class __init__
method. This is what works.
class Decorator:
def __init__(self, arg):
print(arg)
self.arg = arg
def __call__(self, cls):
print(cls)
class Wrapped(cls):
def __init__(self, first_arg, second_arg, **kwargs):
cls.__init__(self, first_arg, second_arg, **kwargs)
print('in wrapped init', self.variable)
return Wrapped
@Decorator('random_string')
class TestClass:
def __init__(self, first_arg, second_arg, **kwargs):
self.variable = 10
print('TestClass init')
test = TestClass(first_arg='one', second_arg='two')
and produces
random_string
<class '__main__.TestClass'>
TestClass init
in wrapped init 10
for some mysterious reasons code is no longer working after removing decorator param (random string in this case)
@Decorator
class TestClass:
def __init__(self, first_arg, second_arg, **kwargs):
self.variable = 10
print('TestClass init')
Output:
Traceback (most recent call last):
File "/home/python_examples/test_decorators.py", line 24, in <module>
test = TestClass(first_arg='one', second_arg='two')
<class '__main__.TestClass'>
TypeError: __call__() got an unexpected keyword argument 'first_arg'
Two questions:
It's because your decorator class takes arg
as a constructor argument. So when you remove your decorator param, make sure that you have removed that parameter from the __init__
method too. Changing this
class Decorator:
def __init__(self, arg):
print(arg)
self.arg = arg
def __call__(self, cls):
print(cls)
class Wrapped(cls):
def __init__(self, first_arg, second_arg, **kwargs):
cls.__init__(self, first_arg, second_arg, **kwargs)
print('in wrapped init', self.variable)
return Wrapped
to this
class Decorator:
def __init__(self):
pass
def __call__(self, cls):
print(cls)
class Wrapped(cls):
def __init__(self, first_arg, second_arg, **kwargs):
cls.__init__(self, first_arg, second_arg, **kwargs)
print('in wrapped init', self.variable)
return Wrapped
will solve your problem.
Actually, this is how it works:
# Assume you have a decorator class and a class named A which is needed to decorate.
@Decorator
class A:
...
# is the same as
class A:
...
A = Decorator()(A)
That's why you need to define __cal__
.
And here you can see that if your Decorator
accepts some parameters to initialize, you need to use something like A = Decorator(xxx)(A)
. And the equivalent in decorator syntax is:
@Decorator(xxx)
class A:
...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.