为什么python在某些事情上使用两个下划线?
我对实际的编程语言还很陌生,而Python是我的第一个。 我对Linux有一点了解,足以应付暑假(我还在读高中),而且在工作中,我有很多空闲时间用来学习Python。
一件事一直让我迷失。 当您拥有以下表达式时,Python中到底有什么不同?
x.__add__(y) <==> x+y
x.__getattribute__('foo') <==> x.foo
我知道什么方法可以做什么,我知道它们可以做什么,但是我的问题是:上面的双下划线方法和它们看上去更简单的等效方法有什么不同?
附言:我不介意关于编程历史的讲座,实际上,我发现了解它非常有用:)如果这些主要是Python的历史方面,请随时开始学习。
7个解决方案
29 votes
这是Python的创建者对其进行解释:
...而不是为 特殊的类方法(例如 作为初始化程序和析构函数),我 决定这些功能可能是 只需要求用户即可处理 用特殊的方法来实现 名称,例如__getattr__、__add__和 等等。 该命名约定是 取自C where标识符 下划线开头保留 由编译器执行,通常会有特殊的 含义(例如,诸如 C预处理程序中的__call__)。
...
我也使用这种技术来允许 用户类以重新定义行为 Python的运算符。 如从前那样 注意,Python是用C实现的, 使用函数指针表 实现各种功能 内置对象(例如“ get 属性”,“添加”和“通话”)。 至 允许定义这些功能 在用户定义的类中,我将 各种特殊的功能指针 方法名称,例如__getattr__, __add__和__call__。有一个 这些之间的直接对应 名称和功能表 指针必须定义何时 在C中实现新的Python对象。
Steven Rumbalski answered 2020-01-20T23:45:18Z
16 votes
当您使用两个下划线(而没有下划线)启动方法时,将应用Python的名称处理规则。 这是一种从其他OO语言(例如C ++和Java)大致模拟private关键字的方法。 (即使如此,该方法在技术上仍然不像Java和C ++方法是私有的那样是私有的,但是从实例外部“很难达到”。)
具有两个前导下划线和两个下划线的方法被认为是“内置”方法,也就是说,它们由解释器使用,并且通常是重载运算符或其他内置功能的具体实现。
mipadi answered 2020-01-20T23:45:44Z
7 votes
好吧,对于程序员来说,力量是件好事,因此应该有一种自定义行为的方法。 像运算符重载(__add__、__div__、__ge__,...),属性访问(__getattribute__、__getattr__(这两个是不同的),__delattr__,...)等。在许多情况下,例如运算符,通常的语法映射为1:1 相应的方法。 在其他情况下,存在一个特殊的过程,该过程有时涉及调用相应的方法-例如,仅当对象不具有请求的属性并且__getattribute__没有实现或引发AttributeError时才调用__getattr__。 其中一些是真正的高级主题,可让您深入了解对象系统的勇气,而很少需要它们。 因此,无需全部学习,只需在需要/想要知道时参考参考。 说到参考,就在这里。
answered 2020-01-20T23:44:43Z
4 votes
它们用于指定Python解释器在特定情况下应使用它们。
例如,__add__函数允许+运算符为自定义类工作。 否则,尝试添加时会出现某种未定义的错误。
Paul Nathan answered 2020-01-20T23:46:08Z
3 votes
从历史的角度来看,前导下划线经常被用作向程序员指示将名称视为定义它们的包/模块/库内部的一种方法。 在不能为私有名称空间提供良好支持的语言中,使用下划线是一种模拟惯例。 在Python中,当您定义一个名为“ __foo__”的方法时,维护程序员会从名称中得知发生了一些特殊的事情,而使用“ foo”的方法并没有发生这种情况。 如果Python选择使用'add'作为内部方法来重载'+',那么您将永远不会有一个带有'add'方法的类而不会引起很多混乱。 下划线提示某些魔术会发生。
William Pursell answered 2020-01-20T23:46:30Z
1 votes
现在,还有许多其他问题被标记为该问题的重复项,并且至少有两个问题询问了__add__方法的调用方式或约定的名称,而现有的答案都没有涵盖这一点,因此:
两者实际上都没有正式名称。
许多开发人员非正式地将它们称为“双重方法”,即“双UNDERscore”。
有些人使用“魔术方法”一词,但这在含糊的含义方法,特殊方法(请参阅下文)或两者之间的某些含义之间有些歧义。
有一个官方术语“特殊属性”,与dunder方法紧密但不完全重叠。 参考资料中的“数据模型”一章从不完全解释什么是特殊属性,但基本思想是至少具有以下一项:
由解释器本身或其内置代码提供的属性,例如函数上的__add__。
属性是解释程序本身实现的协议的一部分,例如+运算符的__add__或用于索引和切片的pickle。
通过忽略实例并直接转到类,允许解释器专门查找的属性,例如再次返回pickle。
大多数特殊属性是方法,但不是全部(例如,不是pickle)。 而且大多数都使用“ dunder”约定,但不是全部(例如,Python 2.x中的迭代器上的next方法)。
同时,大多数dunder方法都是特殊属性,但不是全部-特别是,stdlib或外部库希望定义自己的以相同方式工作的协议(例如2711639430519019063552协议)并不少见。
abarnert answered 2020-01-20T23:47:32Z
0 votes
[推测] Python受Algol68的影响,Guido可能在阿姆斯特丹大学使用过Algol68,其中Algol68具有类似的“踩踏状态”,称为“ Quote踩踏”。 在Algol68中,运算符,类型和关键字可以使用不同的字体显示(通常是**或__underlined__),在源代码文件中,该字体使用引号来实现,例如 'abs'(引用类似于'wikitext'中的引用)
Algol68⇒Python(运算符映射到成员函数)
'和'⇒__and__
'或'⇒__或__
'不'⇒不
'整个'⇒__trunc__
'shl'⇒__lshift__
'shr'⇒__rshift__
'upb'⇒__sizeof__
'long'⇒__long__
'int'⇒__int__
'真实'⇒__float__
'格式'⇒__格式__
'repr'⇒__repr__
'abs'⇒__abs__
负号⇒负__
减号⇒__sub__
加号⇒__添加__
'时间'⇒__mul__
'mod'⇒__mod__
'div'⇒__truediv__
'结束'⇒__div__
'上'⇒__pow__
'im'⇒意象
're'⇒真实
'conj'⇒共轭
在Algol68中,这些被称为粗体名称,例如 abs,但在python中是“ under-under-abs” __ abs__。
我的2分:¢有时,就像幽灵一样,当您将python类剪切并粘贴到Wiki中时,您会神奇地重新生成Algol 68粗体关键字。 ¢
NevilleDNZ answered 2020-01-20T23:49:50Z