我在父类中有一个私有方法def __pickSide(self):
,我想在子类中覆盖它。但是,子类仍然调用继承的def __pickSide(self):
。我该如何覆盖该功能?子类的函数名称与父函数名称完全相同。
答案 0 :(得分:33)
让我们看看最简单的例子:
from dis import dis
class A(object):
def __pick(self):
print "1"
def doitinA(self):
self.__pick()
class B(A):
def __pick(self):
print "2"
def doitinB(self):
self.__pick()
b = B()
b.doitinA() # prints 1
b.doitinB() # prints 2
dis(A.doitinA)
print
dis(B.doitinB)
反汇编如下:
8 0 LOAD_FAST 0 (self)
3 LOAD_ATTR 0 (_A__pick)
6 CALL_FUNCTION 0
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
15 0 LOAD_FAST 0 (self)
3 LOAD_ATTR 0 (_B__pick)
6 CALL_FUNCTION 0
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
正如您所看到的,Python破坏了以两个下划线(以及对这些名称的访问!!)开头的函数名称到包含类名的名称 - 在本例中为_A__pick
和_B__pick
) 。这意味着定义函数的类确定调用哪个__pick
方法。
解决方案很简单,通过删除双下划线来避免伪私有方法。例如,使用_pick
代替__pick
。
答案 1 :(得分:5)
您遇到的问题是,即使在调用中,双下划线也会破坏函数名称。这可以防止多态性正常工作,因为它被修改的名称是基于定义方法的类的名称,而不是被引用的对象的类的名称。用其他东西替换双下划线将解决这个问题。
答案 2 :(得分:3)
使用__foo
名称会破坏方法的名称,以便在需要时更轻松地访问它。我建议永远不要使用它们,这样可以使测试更顺利。
Python中没有私有,如果有,它会阻止你无论如何都这样做。 (这是拥有它的语言中的私人内容。)
表示属性不属于类的公共接口的公共约定,它使用单个前导下划线,如_foo
。这足以使您的代码清晰地将您的内部详细信息与公共API分开。