Search code examples
pythoninheritancetornado

How to do this Class inheritance in Python?


I have a Python/Tornado application that responds to HTTP requests with the following 3 classes:

import tornado.web
class MyClass1(tornado.web.RequestHandler):
    x = 1
    y = 2

    def my_method1(self):
        print "Hello World"


class MyClass2(MyClass1):

    @tornado.web.authenticated
    def get(self):
        #Do Something 1
        pass

    @tornado.web.authenticated
    def post(self):
        #Do Something 2
        pass


class MyClass3(MyClass2):
    pass

I would like all instances MyClass2 to have an instance variable m set to the integer 3. But any instances of MyClass3 should over-ride that and have m set to the integer 4. How can I do it?

I tried adding the following constructors to MyClass2 and MyClass3 respectively, but then when I try to create an instance of MyClass3, I get the following error: TypeError: __init__() takes exactly 1 argument (3 given)

MyClass2.init():

def __init__(self):
    self.m = 3 # This value will be overridden by a subclass

MyClass3.init():

def __init__(self):
    self.m = 4

Solution

  • The tornado.web.RequestHandler already has a __init__ method and Tornado expects it to take two arguments (plus the self argument of a bound method). Your overridden versions don't take these.

    Update your __init__ methods to take arbitrary extra arguments and pass these on via super():

    class MyClass2(MyClass1):
        def __init__(self, *args, **kwargs):
            super(MyClass2, self).__init__(*args, **kwargs)
            self.m = 3
    
        @tornado.web.authenticated
        def get(self):
            #Do Something 1
            pass
    
        @tornado.web.authenticated
        def post(self):
            #Do Something 2
            pass
    
    
    class MyClass3(MyClass2):
        def __init__(self, *args, **kwargs):
            super(MyClass3, self).__init__(*args, **kwargs)
            self.m = 4
    

    You could also use the RequestHandler.initialize() method to set up per-request instance variables; you may have to use super() again to pass on the call to the parent class, if your parent class initialize() does more work than just set self.m.