我对实际的编程语言相当新,而Python是我的第一个。我知道我在Linux上的方式,足以获得暑期工作(我还在高中),在工作中,我有很多空闲时间,我正在学习Python。
有一件事让我感到高兴。当你有像
这样的表达式时,Python究竟有什么不同x.__add__(y) <==> x+y
x.__getattribute__('foo') <==> x.foo
我知道什么方法做什么和做什么,我得到他们做的,但我的问题是:上面的双下划线方法与它们更简单的等价方法有何不同?
P.S。,我不介意在编程历史上讲课,事实上,我觉得知道它非常有用:)如果这些主要是Python的历史方面,请随意开始漫无目的。
答案 0 :(得分:28)
以下是Python explaining it的创建者:
...而不是设计新的语法 特殊种类的方法(如 作为初始化者和析构者),我 决定这些功能可以 通过简单地要求用户来处理 用特殊方法实现方法
__init__
,__del__
和。{ 等等。这个命名惯例是 取自C所在的标识符 以下划线开头是保留的 由编译器经常有特殊的 意义(例如,诸如的宏) C预处理器中的__FILE__
。
...
我也使用这种技术来允许 用户类重新定义行为 Python的运营商。如从前那样 注意到,Python是用C和C实现的 使用函数指针表 实现各种能力 内置对象(例如,“获取 属性“,”添加“和”调用“)。至 允许定义这些功能 在用户定义的类中,我映射了 各种函数指针特殊 方法名称,例如
__getattr__
,__add__
和__call__
。有一个 这些之间的直接对应 名称和功能表 指针必须定义何时 在C中实现新的Python对象。
答案 1 :(得分:16)
当您使用两个下划线(并且没有尾随下划线)启动方法时,将应用Python的name mangling规则。这是一种从其他OO语言(如C ++和Java)中松散模拟private
关键字的方法。 (尽管如此,该方法在技术上仍然不是Java和C ++方法私有的方式,而是从实例外部“更难”获取。)
具有两个前导和两个尾随下划线的方法被认为是“内置”方法,即它们由解释器使用,并且通常是重载运算符或其他内置功能的具体实现。
答案 2 :(得分:7)
嗯,程序员的力量很好,所以应该有一种方法来定制行为。与运算符重载(__add__
,__div__
,__ge__
,...)类似,属性访问(__getattribute__
,__getattr__
(这两者不同),{{ 1}},...)等。在许多情况下,与运算符一样,通常的语法将1:1映射到相应的方法。在其他情况下,有一个特殊的过程,在某些时候涉及调用相应的方法 - 例如,__delattr__
仅在对象没有请求的属性且__getattr__
未实现或引发了AttributeError。其中一些是非常高级的主题,可以让你深入了解对象系统的内容并且很少需要。所以不需要全部学习它们,只需在需要/想知道时查阅参考文献。说到参考,here it is。
答案 3 :(得分:4)
它们用于指定Python解释器应在特定情况下使用它们。
例如,__add__
函数允许+
运算符用于自定义类。否则,在尝试添加时,您将收到某种未定义的错误。
答案 4 :(得分:3)
从历史角度来看,前导下划线经常被用作向程序员指示名称将被视为定义它们的包/模块/库的内部的方法。在不能为私有命名空间提供良好支持的语言中,使用下划线是一种模仿它的惯例。在Python中,当你定义一个名为'__foo__'的方法时,维护程序员会从名称中知道一些特殊情况正在发生,而这种方法并没有发生在名为'foo'的方法上。如果Python选择使用'add'作为重载'+'的内部方法,那么你就永远不会有一个带有'add'方法的类,而不会引起太多混乱。下划线充当了一些神奇的暗示。
答案 5 :(得分:1)
现在将其他一些问题标记为此问题的副本,并且至少有两个问题询问调用__spam__
方法或调用约定的内容,并且现有答案均未涵盖那么,所以:
实际上没有正式名称。
许多开发人员非正式称他们为“Dunder方法”,称为“Double UNDERscore”。
有些人使用“魔术方法”这个术语,但在含义方法,特殊方法(见下文)或两者之间的某些方面之间存在某种模糊之处。
是官方术语“特殊属性”,它与dunder方法紧密但不完全重叠。参考文献中的Data Model章节从未完全解释特殊属性是什么,但基本思想是它至少是下列之一:
__name__
。__add__
运算符的+
或索引和切片的__getitem__
。__add__
。大多数特殊属性是方法,但不是全部(例如,__name__
不是)。并且大多数使用“dunder”约定,但不是全部(例如,Python 2.x中的迭代器上的next
方法)。
与此同时,大多数dunder方法都是特殊属性,但并非全部 - 特别是stdlib或外部库想要定义自己的协议以同样的方式运行并不常见,例如pickle
协议
答案 6 :(得分:0)
[推测] Python受Algol68的影响,Guido可能在University of Amsterdam处使用Algol68,其中Algol68具有类似的“stropping regime”叫做“引用stropping”。在Algol68中,运算符,类型和关键字 可以以不同的字体显示(通常为** 粗体 **,或 __带下划线 em> __),在源代码文件中,这种字体是用引号实现的,例如'abs'(引用类似于'wikitext'中的引用)
在Algol68中,这些被称为粗体名称,例如 abs ,但在python中“abs-under-abs”__abs__。
我的2美分:¢所以有时候 - 就像一个鬼 - 当你将python类剪切并粘贴到wiki中时,你会神奇地转世Algol68的粗体关键字。 ¢