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

发布于 2024-07-06 18:05:59 字数 299 浏览 12 评论 0原文

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

self.__value = 1

def value():
    return self.__value

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

我知道这似乎违背了私有和公共的一般思想,但通常我试图子类化的类是我自己的类之一,我很高兴将成员暴露给子类,但不暴露给该类的实例。 有没有一种干净的方法来提供这种区别?

One of the really nice things about python is the simplicity with which you can name variables that have the same name as the accessor:

self.__value = 1

def value():
    return self.__value

Is there a simple way of providing access to the private members of a class that I wish to subclass? Often I wish to simply work with the raw data objects inside of a class without having to use accessors and mutators all the time.

I know this seems to go against the general idea of private and public, but usually the class I am trying to subclass is one of my own which I am quite happy to expose the members from to a subclass but not to an instance of that class. Is there a clean way of providing this distinction?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无需解释 2024-07-13 18:05:59

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

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

根据记录,“__value”和“value”(以及“_value”)不是同一个名称。 下划线是名称的一部分。

Not conveniently, without further breaking encapsulation. The double-underscore attribute is name-mangled by prepending '_ClassName' for the class it is being accessed in. So, if you have a 'ContainerThing' class that has a '__value' attribute, the attribute is actually being stored as '_ContainerThing__value'. Changing the class name (or refactoring where the attribute is assigned to) would mean breaking all subclasses that try to access that attribute.

This is exactly why the double-underscore name-mangling (which is not really "private", just "inconvenient") is a bad idea to use. Just use a single leading underscore. Everyone will know not to touch your 'private' attribute and you will still be able to access it in subclasses and other situations where it's darned handy. The name-mangling of double-underscore attributes is useful only to avoid name-clashes for attributes that are truly specific to a particular class, which is extremely rare. It provides no extra 'security' since even the name-mangled attributes are trivially accessible.

For the record, '__value' and 'value' (and '_value') are not the same name. The underscores are part of the name.

故事和酒 2024-07-13 18:05:59

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

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

以两个 __ 开头的 Python 名称很特殊,通常您不应该使用这样的名称定义属性。 带有 __ 的名称很特殊,是实现的一部分。 并暴露出来供您使用。

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

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

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

Java 所需的无穷无尽的 getter 和 setter 在 Python 中并不常用。 Python 内省更加灵活,您可以访问对象的属性值的内部字典,并且您拥有一流的 <​​a href="http://docs.python.org/lib/built-in-funcs.html" rel= “nofollow noreferrer”>函数,如getattr()setattr()

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

"I know this seems to go against the general idea of private and public" Not really "against", just different from C++ and Java.

Private -- as implemented in C++ and Java is not a very useful concept. It helps, sometimes, to isolate implementation details. But it is way overused.

Python names beginning with two __ are special and you should not, as a normal thing, be defining attributes with names like this. Names with __ are special and part of the implementation. And exposed for your use.

Names beginning with one _ are "private". Sometimes they are concealed, a little. Most of the time, the "consenting adults" rule applies -- don't use them foolishly, they're subject to change without notice.

We put "private" in quotes because it's just an agreement between you and your users. You've marked things with _. Your users (and yourself) should honor that.

Often, we have method function names with a leading _ to indicate that we consider them to be "private" and subject to change without notice.

The endless getters and setters that Java requires aren't as often used in Python. Python introspection is more flexible, you have access to an object's internal dictionary of attribute values, and you have first class functions like getattr() and setattr().

Further, you have the property() function which is often used to bind getters and setters to a single name that behaves like a simple attribute, but is actually well-defined method function calls.

記憶穿過時間隧道 2024-07-13 18:05:59

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

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

之后,您应该期望您的图书馆的客户不会因为干涉“私人”属性而搬起石头砸自己的脚。

Not sure of where to cite it from, but the following statement in regard to access protection is Pythonic canon: "We're all consenting adults here".

Just as Thomas Wouters has stated, a single leading underscore is the idiomatic way of marking an attribute as being a part of the object's internal state. Two underscores just provides name mangling to prevent easy access to the attribute.

After that, you should just expect that the client of your library won't go and shoot themselves in the foot by meddling with the "private" attributes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文