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
时会引发a。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
可以很容易地由第三方提供,其细节可能随时更改。