Давайте рассмотрим самый простой пример:
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
.