Классы Python не имеют понятия общедоступный/частный, поэтому нам говорят не трогать что-то, что начинается с подчеркивания, если мы это не создали. Но разве для этого не требуется полного знания всех классов, от которых мы прямо или косвенно наследуем? Свидетель:
class Base(object):
def __init__(self):
super(Base, self).__init__()
self._foo = 0
def foo(self):
return self._foo + 1
class Sub(Base):
def __init__(self):
super(Sub, self).__init__()
self._foo = None
Sub().foo()
Ожидаемо, TypeError
возникает при оценке None + 1
. Поэтому я должен знать, что _foo
существует в базовом классе. Чтобы обойти это, вместо этого можно использовать __foo
, что решает проблему, искажая имя. Это кажется если не элегантным, то приемлемым решением. Однако что произойдет, если Base
наследуется от класса (в отдельном пакете )с именем Sub
? Теперь __foo
в моем Sub
переопределяет __foo
в прародителе Sub
.
Это означает, что я должен знать всю цепочку наследования, включая все «частные» объекты, которые каждый из них использует. Тот факт, что Python имеет динамическую -типизацию, еще больше усложняет задачу, так как нет объявлений для поиска. Однако худшая часть, вероятно, заключается в том, что Base
может наследоваться от object
прямо сейчас, но в каком-то будущем выпуске он переключится на наследование от Sub
.Очевидно, что если я знаю, что Sub
унаследован от, я могу переименовать свой класс, как бы это ни раздражало. Но я не могу заглянуть в будущее.
Разве это не тот случай, когда истинный закрытый тип данных предотвратит проблему? Как в Python я могу быть уверен, что случайно не наступлю кому-то на пальцы ног, если эти пальцы могут возникнуть в какой-то момент в будущем?
РЕДАКТИРОВАТЬ:Я, видимо, не ясно изложил основной вопрос. Я знаком с искажением имен и разницей между одинарным и двойным подчеркиванием. Вопрос :в том, как мне справиться с тем фактом, что я могу столкнуться с классами , о существовании которых я сейчас не знаю ? Если мой родительский класс (, который находится в пакете, который я не писал ), начинает наследовать от класса с тем же именем, что и у моего класса, даже изменение имени не поможет. Я ошибаюсь, рассматривая это как (угловой )случай, который могут решить настоящие закрытые члены, но с которым у Python возникают проблемы?
РЕДАКТИРОВАТЬ:По запросу ниже приведен полный пример:
Файлparent.py
:
class Sub(object):
def __init__(self):
self.__foo = 12
def foo(self):
return self.__foo + 1
class Base(Sub):
pass
Файлsub.py
:
import parent
class Sub(parent.Base):
def __init__(self):
super(Sub, self).__init__()
self.__foo = None
Sub().foo()
Называется foo
дедушки и бабушки, но используется мой __foo
.
Очевидно, что вы не стали бы писать такой код самостоятельно, но parent
может быть легко предоставлено третьей стороной, детали которой могут измениться в любое время.