У меня есть закрытый метод def __pickSide(self):
в родительском классе, который я бы хотел переопределить в дочернем классе. Тем не менее, дочерний класс по-прежнему вызывает унаследованный def __pickSide(self):
. Как я могу переопределить функцию? Имя функции дочернего класса точно такое же, как имя родительской функции.
Как переопределить функции родительского класса в python?
Ответ 1
Посмотрите на самый простой пример:
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
.
Ответ 2
Проблема, которую вы видите, заключается в том, что двойные подчеркивания управляют именем функции даже в вызовах. Это предотвращает правильную работу полиморфизма, так как имя, за которое оно искажено, основано на имени класса, в котором определяется метод, а не на имени класса объекта, на который ссылаются. Замена двойных подчеркиваний чем-то другим решит это.
Ответ 3
-
Использование имен
__foo
изменяет имя метода, чтобы сделать его более трудным для доступа к нему, когда вам нужно. Я бы порекомендовал никогда не использовать их, что делает такие вещи, как тестирование, более гладко. -
В Python нет частного, и если бы это было так, это помешало бы вам сделать это в любом случае. (Это точка личных вещей на языках, которые у нее есть.)
-
Общее соглашение, указывающее, что атрибут не является частью общедоступного интерфейса класса, для использования одного ведущего подчеркивания, например
_foo
. Этого достаточно для того, чтобы ваш код четко отделял ваши внутренние данные от вашего общедоступного API.