python中的双下划线

时间:2017-07-24 19:53:55

标签: python

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两次?

2 个答案:

答案 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()