Python中私有和受保护方法的inheritance

我知道,Python中没有“真正的”private / protected方法。 这种方法不是隐藏任何东西,我只是想了解Python的function。

class Parent(object): def _protected(self): pass def __private(self): pass class Child(Parent): def foo(self): self._protected() # This works def bar(self): self.__private() # This doesn't work, I get a AttributeError: # 'Child' object has no attribute '_Child__private' 

那么,这种行为是否意味着“受保护的”方法将会被inheritance,但是“私有的”方法将不会被inheritance?
还是我错过了什么?

Python没有隐私模型,没有像C ++,C#或Java那样的访问修饰符。 没有真正的“保护”或“私人”属性。

带有双下划线和双尾下划线的名称在inheritance时被破坏,以防止冲突。 子类可以定义自己的__private()方法,这些方法不会干扰父类的同名。 这样的名字被认为是私人的 ; 他们仍然可以从课外访问,但意外冲突的可能性要小得多。

通过在这个名字前面加上一个额外的下划线和类名(不pipe名称是如何使用的或者是否存在),来有效地给它们一个命名空间 。 在Parent类中,任何__private标识符在编译时被名称_Parent__private ,而在Child类中,标识符被类定义中的_Child__privatereplace。

以下将起作用:

 class Child(Parent): def foo(self): self._protected() def bar(self): self._Parent__private() 

请参阅词法分析文档中的保留类标识符

__*
类专用名称。 当在类定义的上下文中使用时,这个类中的名称会被重写,使用一个强化的表单来帮助避免基类和派生类的“私有”属性之间的名称冲突。

和参考文件的名称 :

专用名称修改 :当文本在类定义中出现的标识符以两个或更多下划线字符开始,并且不以两个或更多下划线结尾时,它被认为是该类的专用名称。 在为其生成代码之前,专用名称将转换为更长的forms。 该变换插入类名称,删除前导下划线,并在名称前面插入一个下划线。 例如,名为Ham的标识符__spam将被转换为_Ham__spam 。 这种转换与使用标识符的语法上下文无关。

不要使用类专用名称,除非您特别要避免告诉开发人员要将您的类inheritance为不能使用某些名称或冒险破坏类的风险。 在已发布的框架和库之外,这个function几乎没有用处。

还有PEP8说

只使用一个前导下划线用于非公共方法和实例variables。

为了避免名字与子类冲突,使用两个前导下划线来调用Python的名称修改规则。

Python将这些名称与类名称相__a :如果class Foo具有名为__a的属性,则Foo.__a将无法访问该属性。 (一个持久的用户仍然可以通过调用Foo._Foo__a获得访问Foo._Foo__a 。)通常,双Foo._Foo__a下划线应该只用于避免与devise为子类的类中的属性的名称冲突。

_such_methods ,你也应该远离_such_methods 。 我的意思是你应该把他们当作private

__属性更改为_ClassName__method_name ,这使得它比_method_name隐含的语义隐私更私有。

如果你真的喜欢,你可以在技术上仍然可以做到,但是大概没有人会这么做,所以为了维护代码抽象的原因,这个方法在这一点上可能是私有的。

 class Parent(object): def _protected(self): pass def __private(self): print("Is it really private?") class Child(Parent): def foo(self): self._protected() def bar(self): self.__private() c = Child() c._Parent__private() 

这有一个额外的好处(或者说一些主要的好处)允许一个方法不会与子类方法名称相冲突。

通过声明你的数据成员是私人的:

__private()

你根本无法从课堂以外访问它

Python支持一种称为名称修饰的技术。

这个特性将类成员变成前缀两个下划线:

_className.memberName

如果你想从Child()访问它,你可以使用: self._Parent__private()

AFAIK,在第二种情况下,Python执行“name mangling”,所以父类的__private方法的名称实际上是:

 _Parent__private 

而且你也不能以这种forms在小孩身上使用它