Python中+(pos)一元运算符的目的是什么?
一般来说,一元obj应该在Python中做什么?
我问是因为到目前为止,我从未见过这样的情况:
+obj != obj
其中obj是实现+的通用对象。
所以我想知道:为什么存在+和__pos__()? 您能否提供一个真实的示例,其中上面的表达式的计算结果为True?
user16538 asked 2020-01-04T08:17:09Z
6个解决方案
39 votes
这是decimal程序包中的“真实世界”示例:
>>> from decimal import Decimal
>>> obj = Decimal("3.1415926535897932384626433832795028841971")
>>> +obj != obj # The __pos__ function rounds back to normal precision
True
>>> obj
Decimal("3.1415926535897932384626433832795028841971")
>>> +obj
Decimal("3.141592653589793238462643383")
Chris Taylor answered 2020-01-04T08:17:18Z
22 votes
我相信Python运算符受C启发,其中016运算符是出于对称性而引入的(还有一些有用的技巧,请参见注释)。
在PHP或Javascript之类的弱类型语言中,+告诉运行时将变量的值强制为数字。 例如,在Javascript中:
+"2" + 1
=> 3
"2" + 1
=> "21"
Python是强类型的,因此字符串不能用作数字,因此,不能实现一元加号运算符。
当然可以实现+ obj!= obj的对象:
>>> class Foo(object):
... def __pos__(self):
... return "bar"
...
>>> +Foo()
"bar"
>>> obj = Foo()
>>> +"a"
至于实际有意义的示例,请查看超现实的数字。 它们是实数的超集,其中包括无限小值(+ epsilon,-epsilon),其中epsilon是一个小于任何其他正数的正值,但是大于0; 和无限个(+无限,-无限)。
您可以定义0和+0。
尽管0仍未定义,但+0是0 != +0,而1/-epsilon = -infinity。无非就是将x的限制取为1/x,因为从右(+)或从左(-)会发出0。
由于0和+0的行为不同,因此0 != +0是有意义的。
vlopez answered 2020-01-04T08:18:11Z
19 votes
在Python 3.3及更高版本中,Counter使用Counter运算符删除非正计数。
>>> from collections import Counter
>>> fruits = Counter({"apples": 0, "pears": 4, "oranges": -89})
>>> fruits
Counter({"pears": 4, "apples": 0, "oranges": -89})
>>> +fruits
Counter({"pears": 4})
因此,如果Counter中的计数为负或零,则情况为+obj != obj。
>>> obj = Counter({"a": 0})
>>> +obj != obj
True
flornquake answered 2020-01-04T08:18:36Z
5 votes
为了对称,因为一元减号是一个运算符,所以一元加号也必须是运算符。 在大多数算术情况下,它什么都不做,但是请记住,即使不是严格的代数形式,用户也可以定义任意类并将这些运算符用于所需的任何操作。
我知道这是一个旧线程,但是我想扩展现有答案以提供更多示例:
y=+++---+++x可以断言是肯定的,如果不是,则可以抛出异常-这对于检测极端情况非常有用。
该对象可以是多值的(将y=+++---+++x视为单个对象-用于求解二次方程式,对于多分支分析函数,可以将双值函数“折叠”到一个带符号的分支中的任何事物。这包括vlopez提到的±0情况) 。
如果您执行惰性求值,则可能会创建一个函数对象,该函数对象会将某些内容添加到应用于其他内容的内容中。 例如,如果您要逐步解析算术。
作为身份函数传递给某些函数的参数。
对于符号积累的代数结构-阶梯算子等。 当然,可以使用其他功能来完成,但可以想象会看到类似y=+++---+++x的内容。甚至更多,它们不必上下班。 这将构成一个自由的正负组,这可能是有用的。 即使在正式的语法实现中。
野蛮用法:在某种意义上,它可以将计算中的步骤“标记”为“活动”。 收割/播种系统-每个加号都会记住其价值,最后,您可以收集所收集的中间体...因为为什么不呢?
那,加上其他人提到的所有类型转换原因。
毕竟...如果您需要再再有一个操作员,这是很好的。
orion answered 2020-01-04T08:19:38Z
2 votes
这里的许多示例看起来更像是错误。 不过,这实际上是一项功能:
+运算符表示一个副本。
在为标量和数组编写通用代码时,这非常有用。
例如:
def f(x, y):
z = +x
z += y
return z
此函数可在标量和NumPy数组上使用,而无需制作额外的副本,无需更改对象的类型,也不需要任何外部依赖项!
如果您使用了+或类似的东西,则会引入NumPy依赖关系,并将数字强制为NumPy类型,而调用者可能会不希望这样。
如果您执行了+,那么结果将不再是与x相同的类型。在很多情况下都可以,但是如果不是,则不是选择。
如果执行了+,则将创建不必要的副本,这很慢。
如果您做了+,则会执行不必要的乘法,这也很慢。
如果您做到了+ ...我想那行得通,但这很麻烦。
一元+是一个非常不错的选择。
Mehrdad answered 2020-01-04T08:20:44Z
1 votes
Python中存在++i != +i,它为程序员提供了与++i != +i语言类似的可能性-重载运算符,在这种情况下为一元运算符object.__pos__()。
(重载运算符意味着对不同的对象赋予不同的含义,例如,二进制++i != +i在数字和字符串上的行为有所不同-数字在串接字符串时被添加。)
对象可以(与其他对象一起)实现这些模拟数字类型的函数(方法):
__pos__(self) # called for unary +
__neg__(self) # called for unary -
__invert__(self) # called for unary ~
因此++i != +i的含义与object.__pos__()相同-它们是可互换的。
但是++i != +i在眼睛上更容易。
特定对象的创建者可以自由地实现所需的这些功能-正如其他人在现实世界中的示例所示。
我的贡献-开个玩笑:C / C ++中的++i != +i。
MarianD answered 2020-01-04T08:21:32Z