2

关于 python 的真正好处之一是您可以简单地命名与访问器同名的变量:

self.__value = 1

def value():
    return self.__value

有没有一种简单的方法可以访问我希望子类化的类的私有成员?通常我希望简单地使用类中的原始数据对象,而不必一直使用访问器和修改器。

我知道这似乎违背了私有和公共的一般概念,但通常我试图子类化的类是我自己的类之一,我很乐意将成员从子类公开,而不是该类的实例. 有没有提供这种区别的干净方法?

4

3 回答 3

5

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

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

为了记录,' __value'和' value'(和' _value')不是同一个名字。下划线是名称的一部分。

于 2008-10-02T15:06:26.490 回答
3

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

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

以 2 开头的 Python 名称__是特殊的,通常情况下,您不应该用这样的名称定义属性。的名称__是特殊的,并且是实现的一部分。并暴露给您使用。

以 1 开头的名称_是“私人的”。有时它们是隐蔽的,一点点。大多数情况下,“同意的成年人”规则适用——不要愚蠢地使用它们,它们可能会在没有通知的情况下更改。

我们将“私人”放在引号中,因为这只是您和您的用户之间的协议。你已经用 标记了一些东西_。您的用户(和您自己)应该尊重这一点。

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

Java 所需的无穷无尽的 getter 和 setter 在 Python 中并不常用。Python 内省更加灵活,您可以访问对象的内部属性值字典,并且您拥有一流的函数,例如getattr()setattr()

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

于 2008-10-02T21:28:20.113 回答
1

不知道从哪里引用它,但以下关于访问保护的声明是 Pythonic 经典:“我们在这里都是同意的成年人”。

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

在那之后,您应该期望您的图书馆的客户不会通过干预“私人”属性而自取其辱。

于 2008-10-02T17:32:12.910 回答