带有变量和方法的下划线与双下划线[重复]

Posted

技术标签:

【中文标题】带有变量和方法的下划线与双下划线[重复]【英文标题】:Underscore vs Double underscore with variables and methods [duplicate] 【发布时间】:2011-10-19 07:09:02 【问题描述】:

有人很好地向我解释 __method() 出错了,但由于还有很多其他人需要帮助,所以我没有进一步打扰他,我想知道是否有人可以进一步详细说明这些差异。

例如,我不需要修改,但 _ 是否保持私有,因此有人无法执行 instance._method()?或者它只是通过使其唯一来防止它覆盖另一个变量?我不需要“隐藏”我的内部方法,但由于它们是特定于使用的,我不希望它们在课堂之外使用。

【问题讨论】:

【参考方案1】:

来自PEP 8:

_single_leading_underscore:弱“内部使用”指标。例如

from M import *

不导入名称以下划线开头的对象。

single_trailing_underscore_:按惯例使用,以避免与 Python 关键字冲突,例如

Tkinter.Toplevel(master, class_='ClassName')

__double_leading_underscore:命名类属性时,调用名称 mangling(在FooBar__boo 类内部变为_FooBar__boo;见下文)。

__double_leading_and_trailing_underscore__:“魔法”对象或 存在于用户控制的命名空间中的属性。例如。 __init__, __import____file__。永远不要发明这样的名字;只使用它们 记录在案。

另外,来自 David Goodger 的Code Like a Pythonista:

属性:interface_internal__private

但尽量避免使用__private 形式。我从不使用它。相信我。如果你 使用它,你会后悔的。

解释:

具有 C++/Java 背景的人特别容易 过度使用/滥用此“功能”。但是__private 名称不起作用 与 Java 或 C++ 中的方式相同。他们只是触发了一个名字修改 目的是防止子类中发生意外的命名空间冲突: MyClass.__private 就变成了MyClass._MyClass__private。 (注意 即使这对于与 超类,例如不同模块中的子类。) 从他们的班级之外访问__private 名字,只是不方便和 脆弱(它添加了对超类的确切名称的依赖)。

问题是一个类的作者可能会合理地认为“这 属性/方法名称应该是私有的,只能从内部访问 此类定义”并使用__private 约定。但稍后, 该类的用户可以创建一个合法需要的子类 访问该名称。所以要么必须修改超类 (这可能很困难或不可能),或者子类代码必须 使用手动修改的名称(这充其量是丑陋和脆弱的)。

Python 中有一个概念:“我们在这里都是成年人”。如果 你使用__private 表单,你在保护谁的属性? 子类有责任使用来自 正确的超类,超类的责任是 正确记录它们的属性。

最好使用单前导下划线约定, _internal。 “这根本不是名字错位;它只是表明 其他人要“小心这个,这是一个内部实现 细节;不完全理解就不要碰它”。它只是一个 不过约定。

【讨论】:

我并没有真正理解为什么不使用私有方法的解释——我的意思是在 Java 和 Co 中可以提出完全相同的论点,但是到目前为止,Java 程序仍然可以工作,尽管它们使用了很多私有方法(子类不能使用) @Voo 当然,它们可以工作,但它的背后是一个痛苦,坦率地说,大多数只是导致在 Java 社区中不必要的夸大其词。 在其他语言中,将字段/方法从私有更改为公共仅意味着一行更改(将定义中的“private”关键字更改为“public”)。在 Python 中,您必须更改属性名称,这意味着在调用它的位置也要更改它。不完全是 PITA,但更容易出错。 我同意“我们都是同意的成年人”,但由于 python 支持后期绑定,这可能很危险。您可能会意外地覆盖子类的方法,从而破坏代码。没有什么会告诉你你这样做了,而且很难找到。 IDE 应该支持关于这个问题的警告。有人知道支持此类警告的好 IDE 吗?就像 Visual Studio 为 c# 做的那样。 @Invader pylint【参考方案2】:

Python 中没有访问控制。您可以访问一个类的所有属性,其中包括错误名称(如_class__variable)。专注于您的代码和 API,而不是试图保护开发人员免受自己的伤害。

【讨论】:

【参考方案3】:

单个前导下划线只是一个约定,意思是“您可能不应该使用它”。它不会阻止某人使用该属性。

双前导下划线实际上改变了属性的名称,以便继承层次结构中的两个类可以使用相同的属性名称,并且它们不会发生冲突。

【讨论】:

我喜欢这个解释!!如此简短和甜蜜,但清楚地传达了整个概念。我只会添加一个名称更改的示例:Class1 和 Class2 中的 __foo() 如何变为 _Class1__foo() 和 _Class2__foo()

以上是关于带有变量和方法的下划线与双下划线[重复]的主要内容,如果未能解决你的问题,请参考以下文章

python 里面的单下划线与双下划线的区别

Python中的私有变量和方法[重复]

python面向对象面试集锦(1-23)

学习笔记——使用下划线命名的规则

Excel VBA在带有变量的页脚内开始和停止下划线

如何在android中创建带有下划线文本的Textview [重复]