Как переопределить функции родительского класса в python?

у меня есть собственный метод def __pickSide(self): в родительском классе, который я хотел бы переопределить в дочернем классе. Однако дочерний класс по-прежнему вызывает унаследованный def __pickSide(self):. Как я могу переопределить функцию? Имя функции дочернего класса точно совпадает с именем родительской функции.

3 ответов


давайте рассмотрим самый простой пример:

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.


проблема, которую вы видите, заключается в том, что двойное подчеркивание искажает имя функции даже при вызовах. Это предотвращает правильную работу полиморфизма, поскольку имя, на которое он искажается, основано на имени класса, в котором определен метод, а не на имени класса объекта, на который ссылаются. Замена двойных подчеркиваний чем-то другим решит эту проблему.


  • используя __foo имена искажает имя метода, чтобы сделать его более хлопот, чтобы получить к нему доступ, когда вам нужно. Я бы рекомендовал никогда не использовать их, что делает такие вещи, как тестирование, более гладкими.

  • в Python нет частного, и если бы он был, это все равно помешало бы вам это сделать. (В этом смысл личных вещей на языках, которые имеют это.)

  • общее соглашение, указывающее, что атрибут не является частью открытого интерфейса класса, чтобы использовать один из ведущих подчеркивания, как _foo. Этого достаточно для того, чтобы ваш код четко отделял ваши внутренние данные от вашего публичного API.