简体   繁体   中英

Python Inheritance: Calling Methods Inside Methods

I'm new to Python and trying to understand the best "Pythonic" practices for OO and inheritance.

Here's a simplified version of something I'm trying to do: Let's say I have a base class A that has an initialization method, which, in turn, calls another method that sets some internal parameters -- I'd like to have the latter method accessible to clients as an independent function/service that can be reused after initialization:

class A(object):

    def __init__(self):

        print "Entered A's __init__"

        #Initialization specific to A:
        print "Calling A's set_params"
        self.set_params()

    def set_params(self):

        print "Entered A's set_params"      

        #Parameter setting specific to A:
        #...

Then as expected, the output of A() prints the following:

Entered A's __init__
Calling A's set_params
Entered A's set_params

So far there's no problem. Next, I add a sub class B that inherits from A but has more specific tasks going on in addition to the inherited ones:

class B(A):

    def __init__(self):

        print "Entered B's __init__"

        #Inheriting initialization from A:
        print "Calling A's __init__"
        super(B, self).__init__()

        #More initialization specific to B:
        #...

    def set_params(self):

        print "Entered B's set_params"

        #Inheriting parameter setting from A:
        print "Calling A's set_params"
        super(B, self).set_params()

        #More parameter setting specific to B:
        #...

The problem is that I expect the initializer A.__init__ called by B.__init__ to operate completely independently of how I'm overriding the functions of B , so that overriding the functions of B does not change the behavior of A when instantiating B . In this case, I need A.__init__ to call A.set_params as before rather than calling B.set_params , and disregard the fact that the latter is being overridden.

In other words, in this case I obtain the following output after running B() :

Entered B's __init__
Calling A's __init__
Entered A's __init__
Calling A's set_params
Entered B's set_params
Calling A's set_params
Entered A's set_params

And the question is, what should I do to get this instead after running B() ?

Entered B's __init__
Calling A's __init__
Entered A's __init__
Calling A's set_params
Entered A's set_params

The problem would disappear if I simply got rid of A.set_params and put its code content inside A.__init__ , but as I mentioned, I'd like it to be separate and accessible by client code independently.

I understand that it has something to do with the fact that functions are bound to instances in this case rather than to classes , and I have tried static methods, class methods, and abstract methods as well, but I could not figure out the correct combination to solve this problem.

Some insight would be greatly appreciated! :-)

Yeah, designing for inheritance is tricky like that. People don't put as much thought as they really should into what overridden methods do or don't affect, and they don't do enough to document how overriding methods affects other methods.

If you want to bypass overrides for that set_params call, you can explicitly specify which class's method you want to call:

class A(object):
    def __init__(self):
        ...
        A.set_params(self)

or you can add a __set_params method that won't get overridden and call that from __init__ and set_params :

class A(object):
    def __init__(self):
        ...
        self.__set_params()
    def set_params(self):
        self.__set_params()
    def __set_params(self):
        # actual implementation here

One way, you have to type out the class name explicitly every time, and the other way, you have to write up another method definition. Which one works better depends on how long your class name is and how many times you need to use the method.

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