Why do I need to repeat method definition while using django.utils.decorators method_decorator in inherited class
-
06-12-2019 - |
Question
Hi I am trying to understand the django.utils.decorators method_decorator decorator. The method_decorator turns a function decorator into a class method decorator.
The source for this decorator is at (https://github.com/django/django/blob/master/django/utils/decorators.py)
My example function decorator:
def run_eight_times(myfunc):
def inner_func(*args, **kwargs):
for i in range(8):
myfunc(*args, **kwargs)
return inner_func
My example base class:
class Myclass(object):
def __init__(self,name,favorite_dish):
self.name = name
self.favorite_dish = favorite_dish
def undecorated_function(self):
print "%s likes spam in his favorite dish %s" % (self.name,self.favorite_dish)
Now I want to create an inherited class that uses the django.utils.decorators method_decorator to decorate the Myclass method undecorated_function. To get the method_decorator to work I need to redefine the function in the inherited class.
So This works:
class Myrepetitiveclass(Myclass):
def __init__(self,*args, **kwds):
Myclass.__init__(self,*args,**kwds)
@method_decorator(run_eight_times)
def undecorated_function(self):
print "%s likes spam in his favorite dish %s" % (self.name,self.favorite_dish)
noisier_me = Myrepetitiveclass("harijaynoisyclass","moreeggs")
noisier_me.undecorated_function()
I am a little confused and dont know why the code below does not work and gives a syntax error.
This does not get interpreted correctly and gives a syntax error.
class Myrepetitiveclass(Myclass):
def __init__(self,*args, **kwds):
Myclass.__init__(self,*args,**kwds)
# Why does this not work? and gives a syntax error?
@method_decorator(run_eight_times)
self.undecorated_function
How do I decorate a function in the child class without redefining it?
La solution
self
doesn't exist in that scope - it only exists inside a method, and only then because it's passed as the first parameter.
The way to do this is to override the method, and simply call the super class method:
@method_decorator(run_eight_times)
def undecorated_function(self):
super(Myrepetitiveclass, self).undecorated_function()
Also, two comments on your other code: there's no point overriding the __init__
method if you're just calling the parent method, but if you do need to that you should use super
as I have done here, rather than using the name of the superclass itself.