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.