【发布时间】:2012-07-23 07:03:10
【问题描述】:
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()
预计会在评估 None + 1 时引发 TypeError。所以我必须知道_foo 存在于基类中。为了解决这个问题,可以改用__foo,它通过修改名称来解决问题。这似乎是一个可以接受的解决方案,如果不是优雅的话。但是,如果Base 继承自一个名为Sub 的类(在单独的包中),会发生什么情况?现在我的Sub 中的__foo 覆盖了祖父母Sub 中的__foo。
这意味着我必须知道整个继承链,包括每个使用的所有“私有”对象。 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 可以很容易地由第三方提供,其细节可能随时更改。
【问题讨论】:
-
您能否发布一个示例来证明这一点,其中另一个同名课程不会完全影响您现有的课程?..或者我仍然不理解..没关系...我做了一个,你的权利我猜这是一个极端情况......只是尽量不要使用我猜的常见私有变量/类名