python 下划线逗号_为什么python在某些事情上使用两个下划线?

为什么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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值