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

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

12
задан wrongusername 20 March 2010 в 18:30
поделиться

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 .

33
ответ дан 2 December 2019 в 03:38
поделиться

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

5
ответ дан 2 December 2019 в 03:38
поделиться
  • Использование __ foo names искажает имя метода, чтобы затруднить доступ к нему, когда вам это нужно. Я бы порекомендовал никогда их не использовать, потому что такие вещи, как тестирование, проходят более гладко.

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

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

3
ответ дан 2 December 2019 в 03:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: