我是Python的新手,并试图了解OO和继承的最佳“Pythonic”实践。
这是我正在尝试做的事情的简化版本:假设我有一个基类A
,它有一个初始化方法,反过来,它调用另一个设置一些内部参数的方法 - 我我希望客户端可以访问后一种方法,作为一个可以在初始化后重用的独立函数/服务:
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:
#...
然后按预期,A()
的输出打印以下内容:
Entered A's __init__
Calling A's set_params
Entered A's set_params
到目前为止没有问题。接下来,我添加一个继承自B
的子类A
,但除了继承的任务外,还有更多特定任务:
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:
#...
问题是,我希望A.__init__
调用的初始值设定项B.__init__
完全独立地操作我如何覆盖B
的功能,所以在实例化B
时,覆盖A
的功能不会改变B
的行为。在这种情况下,我需要A.__init__
像以前一样调用A.set_params
而不是调用B.set_params
,而忽略后者被覆盖的事实。
换句话说,在这种情况下,我在运行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
问题是,在运行B()
之后我应该怎么做?
Entered B's __init__
Calling A's __init__
Entered A's __init__
Calling A's set_params
Entered A's set_params
如果我简单地删除A.set_params
并将其代码内容放在A.__init__
中,问题就会消失,但正如我所提到的,我希望它是独立的,并且可以由客户端代码独立访问。
我理解它与函数绑定到实例这一事实有关,而不是 classes ,我尝试过静态方法,类方法和抽象方法,但我无法找出解决这个问题的正确组合。
非常感谢一些见解! : - )
答案 0 :(得分:3)
是的,继承设计很棘手。人们并没有像他们真正应该对被覆盖的方法做什么或不做什么那样多考虑,并且他们没有做足够的事情来记录覆盖方法如何影响其他方法。
如果要绕过该set_params
调用的覆盖,您可以明确指定要调用哪个类的方法:
class A(object):
def __init__(self):
...
A.set_params(self)
或者您可以添加一个不会被覆盖的__set_params
方法,并从__init__
和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
一种方法是,每次都必须明确地输入类名,另一方面,你必须编写另一个方法定义。哪一个更好用取决于您的班级名称的长度以及您需要使用该方法的次数。