简体   繁体   中英

Python Parent/Child class method call

Python 2.7.6 on Linux.

I'm using a test class that inherits from a parent. The parent class holds a number of fields that are common to many child classes, and I need to call the parent setUp method to initialize the fields. Is calling ParentClass.setUp(self) the correct way to do this? Here's a simple example:

class RESTTest(unittest.TestCase):
    def setUp(self):
        self.host = host
        self.port = port
        self.protocol = protocol
        self.context = context

class HistoryTest(RESTTest):
    def setUp(self):
        RESTTest.setUp(self)
        self.endpoint = history_endpoint
        self.url = "%s://%s:%s/%s/%s" %(self.protocol, self.host, self.port, self.context, self.endpoint)

    def testMe(self):
        self.assertTrue(True)

if __name__ == '__main__':
    unittest.main()

Is this correct? It seems to work.

You would use super for that.

super(ChildClass, self).method(args)

class HistoryTest(RESTTest):
    def setUp(self):
        super(HistoryTest, self).method(args)
        ...

In Python 3 you may write:

class HistoryTest(RESTTest):
    def setUp(self):
        super().method(args)
        ...

which is simpler.

See this answer :

super() lets you avoid referring to the base class explicitly, which can be nice. But the main advantage comes with multiple inheritance, where all sorts of fun stuff can happen. See the standard docs on super if you haven't already.

Multiple inheritance

To (try to) answer the question in your comment:

How do you specify which super method you want to call?

From what I understand of the philosophy of multiple inheritance (in Python), you don't. I mean, super , along with the Method Resolution Order (MRO) should do things right and select the appropriate methods. (Yes methods is a plural, see below.)

There are a lot of blog posts / SO answers about this you can find with keywords " multiple inheritance ", " diamond ", " MRO ", " super ", etc. This article provides a Python 3 example I found surprising and didn't find in other sources:

class A:
    def m(self):
        print("m of A called")

class B(A):
    def m(self):
        print("m of B called")
        super().m()

class C(A):
    def m(self):
        print("m of C called")
        super().m()

class D(B,C):
    def m(self):
        print("m of D called")
        super().m()

D().m()

m of D called
m of B called
m of C called
m of A called

See? Both Bm() and Cm() are called thanks to super , which seems like the right thing to do considering D inherits from both B and C .

I suggest you play with this example like I just did. Adding a few print s, you'll see that, when calling D().m() , the super().m() statement in class B itself calls Cm() . Whereas, of course, if you call B().m() ( B instance, not D instance), only Am() is called. In other words, super().m() in B is aware of the class of the instance it is dealing with and behaves accordingly.

Using super everywhere sounds like the silver bullet, but you need to make sure all classes in the inheritance schema are cooperative (another keyword to dig for) and don't break the chain, for instance when expecting additional parameters in child classes.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM