Python没有隐私模型,没有像C ++,C#或Java这样的访问修饰符。没有真正的“受保护”或“私有”属性。
带有前导双下划线但无尾随双下划线的名称将被重编,以防止继承时出现冲突。子类可以定义自己的__private()
方法,并且不会干扰父类上的相同名称。这些名称被认为是私人的; 他们仍然可以从班级外部访问,但是发生意外冲突的可能性要小得多。
通过在此类名称前加上一个额外的下划线和类名称(无论名称如何使用或是否存在),来进行改型,从而有效地为它们提供一个命名空间。在Parent
类中,任何__private
标识符都将由name替换(在编译时)_Parent__private
,而在Child
类中_Child__private
,在类定义中的任何地方,标识符均由替换。
以下将起作用:
class Child(Parent):
def foo(self):
self._protected()
def bar(self):
self._Parent__private()
请参阅词法分析文档中的标识符的保留类:
__*
类私有名称。当在类定义的上下文中使用时,此类别中的名称将被重写以使用变形的形式,以帮助避免基类和派生类的“私有”属性之间的名称冲突。
以及有关名称的参考文档:
私有名称修饰:当在类定义中以文本形式出现的标识符以两个或多个下划线字符开头且不以两个或多个下划线结尾时,则被视为该类的私有名称。在为专用名称生成代码之前,专用名称会转换为更长的格式。转换将在该类的名称前面插入类名,并删除前导下划线,并插入单个下划线。例如,__spam
出现在名为Ham的类中的标识符将转换为_Ham__spam
。此转换独立于使用标识符的句法上下文。
不要使用类专用名称,除非您特别想避免告诉那些想要对您的类进行子类化的开发人员,他们不能使用某些名称或冒着破坏您的类的风险。在已发布的框架和库之外,此功能很少使用。
该PEP 8 Python的风格指南是这样说的关于私人名字改编:
如果您的类打算被子类化,并且您具有不希望使用子类的属性,请考虑使用双引号和下划线来命名它们。这将调用Python的名称修改算法,其中将类的名称修改为属性名称。这有助于避免属性名称冲突,如果子类无意中包含相同名称的属性。
注1:请注意,整齐的名称中仅使用了简单的类名,因此,如果子类同时选择了相同的类名和属性名,则仍会发生名称冲突。
注意2:名称修饰可以使某些用途(如调试和
__getattr__()
)变得不太方便。但是,名称修饰算法已被详细记录,并且易于手动执行。
注意3:并非每个人都喜欢名称修饰。尝试在避免意外名称冲突与高级呼叫者潜在使用之间进行权衡。