使用私有成员对类进行子类化

时间:2008-10-02 14:59:19

标签: python oop encapsulation

关于python的一个非常好的事情是,你可以简单地命名与访问者同名的变量:

self.__value = 1

def value():
    return self.__value

是否有一种简单的方法可以提供对我希望子类化的类的私有成员的访问权限?通常我希望简单地使用类中的原始数据对象,而不必一直使用访问器和变换器。

我知道这似乎与私有和公共的一般概念背道而驰,但通常我尝试子类的类是我自己的类,我很乐意将成员公开给子类而不是实例那个班。是否有一种干净的方式来提供这种区别?

3 个答案:

答案 0 :(得分:5)

不方便,不进一步破坏封装。双下划线属性通过在其所访问的类前面添加'_ClassName'来进行名称修改。因此,如果您有一个具有'__value'属性的'ContainerThing'类,则该属性实际上存储为'{ {1}}”。更改类名(或重构属性的位置)将意味着破坏尝试访问该属性的所有子类。

这正是为什么双下划线名称修改(这不是真正的“私有”,只是“不方便”)是一个坏主意使用。只需使用单个前导下划线。每个人都知道不要触摸你的“私人”属性,你仍然可以在子类和其他方便的情况下访问它。双重下划线属性的名称修改仅用于避免特定于特定类的属性的名称冲突,这种情况极为罕见。它没有提供额外的“安全性”,因为即使是名称错误的属性也可以轻易访问。

对于记录,“_ContainerThing__value”和“__value”(和“value”)的名称不同。下划线是名称的一部分。

答案 1 :(得分:3)

“我知道这似乎违背了私有和公共的一般概念”并非真正“反对”,只是与C ++和Java不同。

私有 - 用C ++和Java实现并不是一个非常有用的概念。有时,它有助于隔离实现细节。但它过度使用了。

以两个__开头的Python名称是特殊的,作为正常情况,您不应该使用这样的名称定义属性。 __的名称是特殊的,是实现的一部分。并露出供您使用。

以一个_开头的名称是“私有”。有时它们被隐藏了一点点。大多数情况下,“同意成人”规则适用 - 不要愚蠢地使用它们,它们如有变更,恕不另行通知。

我们将“私人”放在引号中,因为它只是您和您的用户之间的协议。您已使用_标记了内容。您的用户(以及您自己)应该尊重这一点。

通常,我们的方法函数名称带有前导_,表示我们认为它们是“私有的”,如有更改,恕不另行通知。

Java所需的无尽的getter和setter并不像Python中常用的那样。 Python内省更灵活,您可以访问对象的属性值内部字典,并且您有getattr()setattr()这样的第一个类functions

此外,您有property()函数,它通常用于将getter和setter绑定到一个行为类似于简单属性的名称,但实际上是定义良好的方法函数调用。

答案 2 :(得分:1)

不确定从何处引用它,但以下有关访问保护的声明是Pythonic canon:“我们都在这里同意成年人”。

正如Thomas Wouters所说,单一的前导下划线是将属性标记为对象内部状态的一部分的惯用方法。两个下划线仅提供名称修改以防止轻松访问属性。

在那之后,你应该只是期望你的图书馆的客户不会通过干涉“私人”属性而自拔。