Chr*_*ris 7 python private subclass
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()
Run Code Online (Sandbox Code Playgroud)
预计TypeError会在None + 1评估时提高.所以我必须知道_foo基类中存在的东西.为了解决这个问题,__foo可以使用它,通过修改名称来解决问题.这似乎是一种可接受的解决方案,如果不是优雅的话.但是,如果Base从类(在单独的包中)继承,会发生什么Sub?现在__foo,我在祖父母的Sub覆盖.__fooSub
这意味着我必须知道整个继承链,包括每个使用的所有"私有"对象.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
Run Code Online (Sandbox Code Playgroud)
档案sub.py:
import parent
class Sub(parent.Base):
def __init__(self):
super(Sub, self).__init__()
self.__foo = None
Sub().foo()
Run Code Online (Sandbox Code Playgroud)
祖父母foo被称为,但我__foo被使用了.
显然你不会自己编写这样的代码,但parent可以很容易地由第三方提供,其细节可能随时改变.
class Sub(Base):
def __init__(self):
super(Sub, self).__init__()
self.__foo = None
# ^^
Run Code Online (Sandbox Code Playgroud)
会不会产生冲突_foo或__foo在Base.这是因为Python用单个下划线和类的名称替换双下划线; 以下两行是等效的:
class Sub(Base):
def x(self):
self.__foo = None # .. is the same as ..
self._Sub__foo = None
Run Code Online (Sandbox Code Playgroud)
(响应编辑:)类层次结构中的两个类不仅具有相同的名称,而且它们都使用相同的属性名,并且都使用私有的mangled(__)形式的可能性非常小,以至于它在实践中可以安全地忽略(到目前为止我还没有听说过一个案例).
然而,从理论上讲,你是正确的,为了正式验证程序的正确性,人们最了解整个继承链.幸运的是,正式验证通常需要一组固定的库.
这是禅宗的精神,包括
实用性胜过纯洁.