如何在python中覆盖父类的函数?

时间:2010-03-20 18:30:38

标签: python inheritance override parent

我在父类中有一个私有方法def __pickSide(self):,我想在子类中覆盖它。但是,子类仍然调用继承的def __pickSide(self):。我该如何覆盖该功能?子类的函数名称与父函数名称完全相同。

3 个答案:

答案 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分开。