用私人成员将类子类化
关于python真正的好处之一就是它的简单性,我们可以使用它来命名与访问器同名的变量:
self.__value = 1 def value(): return self.__value
有没有一种简单的方法可以提供对我希望子类化的类的私有成员的访问权限?通常,我希望只使用类中的原始数据对象,而不必始终使用访问器和变异器。
我知道这似乎违背了私有和公共的一般想法,但是通常我要尝试子类化的类是我自己的类,我很高兴将成员暴露给子类而不是该类的实例。有没有提供这种区别的干净方法?
解决方案
不方便,没有进一步破坏封装。 double-underscore属性通过在要访问的类的前面加上" _ClassName"来进行名称修饰。因此,如果我们具有" __value"属性的" ContainerThing"类,则该属性实际上存储为""。 _ContainerThing__value
"。更改类名称(或者重构分配属性的位置)将意味着破坏所有尝试访问该属性的子类。
这就是为什么使用双下划线"-"(不是真正的"私有",只是"不便")是一个不好的主意。只需使用单个前导下划线即可。每个人都知道不要触摸"私有"属性,并且我们仍然可以在子类和其他需要简化的情况下访问它。双下划线属性的名称处理仅在避免真正针对特定类的属性发生名称冲突时非常有用,这种情况极为罕见。它没有提供额外的"安全性",因为即使名称混杂的属性也可以轻松访问。
为了记录," __ value"和" value"(以及" _value""的名称不同)。下划线是名称的一部分。
不确定从何处引用它,但是以下关于访问保护的声明是Pythonic规范:"我们都同意这里的成年人"。
就像托马斯·沃特斯(Thomas Wouters)所说的那样,单个下划线是将属性标记为对象内部状态的一部分的惯用方式。两个下划线仅提供名称修饰,以防止轻松访问该属性。
在那之后,我们应该只希望图书馆的客户不会通过干预"私有"属性而自嘲。
"我知道这似乎违背了私有和公共的一般概念。"并不是真的"反对",只是与C ++和Java不同。
用C ++和Java实现的私有不是一个非常有用的概念。有时,它有助于隔离实现细节。但这是过度使用的方式。
以两个`__'开头的Python名称是特殊的,通常不应该使用这样的名称来定义属性。带有____的名称是特殊的,并且是实现的一部分。并暴露给我们使用。
以" _"开头的名称是"私有"。有时它们被隐藏了一点。在大多数情况下,"同意成年人"规则适用-不要愚蠢地使用它们,它们如有更改,恕不另行通知。
我们将"私人"用引号引起来,因为这只是我们和用户之间的协议。我们已用" _"标记事物。用户(和我们自己)应该尊重这一点。
通常,我们使用带有前缀" _"的方法函数名称来表示我们认为它们是"私有"的,并且如有更改,恕不另行通知。
Java所需的无休止的getter和setter方法在Python中并不常用。 Python自省更灵活,我们可以访问对象的内部属性值字典,并且具有一流的函数,例如getattr()
和setattr()
。
此外,我们具有property()
函数,该函数通常用于将getter和setter绑定为一个行为简单的属性,但实际上是定义明确的方法函数调用的名称。