class A(object):
def __get(self):
pass
def _m(self):
return self.__get()
class B(A):
def _m(self):
return str(self.__get())
print(A()._m())
print(B()._m())
为什么print(A()._m())
打印None
,但print(B()._m())
会提出AttributeError: 'B' object has no attribute '_B__get'
?
我认为双下划线可以防止方法覆盖。
更新
您认为__get
是私有的。
那为什么以下工作?
class A(object):
def __get(self):
pass
def _m(self):
return self.__get()
class B(A):
pass
print(A()._m())
print(B()._m())
为什么此代码不会提升AttributeError
并打印None
两次?
答案 0 :(得分:8)
前导双下划线名称为private
(意味着派生类不可用)
这不是万无一失的。它是通过修改名称来实现的。 Python Documentation说:
表单__spam的任何标识符(至少两个前导下划线, 最多一个尾随下划线)在文本上被替换为 _classname__spam,其中classname是当前的类名,其中前导下划线被剥离。这种破坏是不加考虑的 到标识符的句法位置,因此它可以用于 定义类 - 私有实例和类变量,方法,变量 存储在全局变量中,甚至存储在实例中的变量。私人的 这个类在其他类的实例上。
因此,{A}实际上已将__get
修改为A _A__get
。当B类尝试引用__get
时,它会被修改为_B__get
,但不匹配
换句话说,在类Xyzzy中定义的__plugh意味着"除非你以Xyzzy类运行,否则你不应该触及__plugh。"
答案 1 :(得分:0)
对于A类的_ _methodName()
成员函数,
从类A外部调用此成员函数,您只能调用_A__methodName()
(尝试调用__methodName()
会产生错误。)
如果在类A中调用此成员函数,则可以同时使用_A__methodName()
和__methodName()
。