Как переопределить функции родительского класса в 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.