一般来说,一元+
应该在Python中做什么?
我问,因为到目前为止,我从未见过这样的情况:
+obj != obj
obj
是实现__pos__()
的通用对象。
所以我想知道:为什么+
和__pos__()
存在?您能否提供一个真实示例,其中上面的表达式求值为True
?
答案 0 :(得分:39)
以下是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')
答案 1 :(得分:22)
我认为Python操作符受C的启发,+
运算符是为了对称而引入的(还有一些有用的hacks,请参阅注释)。
在弱类型语言(如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"
至于它实际上有意义的例子,请查看 surreal numbers。他们是实物的超集,其中包括 无穷小的值(+ epsilon, - epsilon),其中epsilon是 一个小于任何其他正数的正值,但是 大于0;和无限的(+无穷大, - 无穷大)。
您可以定义epsilon = +0
和-epsilon = -0
。
虽然1/0
仍未定义,但1/epsilon = 1/+0
为+infinity
,1/-epsilon
= -infinity
。它是
只是从右侧(+)或左侧( - )获取1/x
x
aproaches 0
的限制。
由于0
和+0
行为不同,因此0 != +0
才有意义。
答案 2 :(得分:17)
在Python 3.3及更高版本中,collections.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
答案 3 :(得分:5)
对于对称性,因为一元减号是一个算子,一元加号也必须是。在大多数算术情况下,它不会做任何事情,但请记住,用户可以定义任意类并将这些运算符用于他们想要的任何内容,即使它不是严格的代数。
我知道这是一个旧线程,但我想扩展现有的答案以提供更广泛的例子:
+
可以断言积极性并抛出异常,如果不是 - 检测极端情况非常有用。±sqrt(z)
视为单个对象 - 用于求解二次方程,用于多分支分析函数,任何可以将二值函数“折叠”到带有符号的一个分支中的任何内容。这包括vlopez提到的±0案例。y=+++---+++x
这样的东西。更重要的是,他们不必通勤。这构建了一个免费的正和负组,这可能是有用的。即使在正式的语法实现中也是如此。那,加上其他人提到的所有类型转换原因。
毕竟......如果你需要的话,还有一个操作员很高兴。
答案 4 :(得分:2)
这里的许多示例看起来更像是bug。不过,这实际上是一项功能:
+
运算符表示副本。在为标量和数组编写通用代码时,这非常有用。
例如:
def f(x, y):
z = +x
z += y
return z
此功能适用于标量和 NumPy数组无需进行额外的复制,而无需可以更改对象,并且没有需要任何外部依赖项!
如果您使用numpy.positive
或类似的东西,则会引入NumPy依赖关系,并将数字强制为NumPy类型,而调用者可能会不希望这样。
如果您进行了z = x + y
,则结果将不再是与x
相同的类型。在许多情况下都可以,但如果不是,则不是一种选择。
如果您执行了z = --x
,则将创建不必要的副本,这很慢。
如果您进行了z = 1 * x
,则将执行不必要的乘法,这也很慢。
如果您做了copy.copy
...我想那是可行的,但这很麻烦。
一元+
是一个非常不错的选择。
答案 5 :(得分:1)
__pos__()
存在于 Python 中,为程序员提供与 C++
语言 - 重载运算符类似的可能性,在这种情况下,一元运算符 +
。
(重载运算符意味着为不同的对象提供不同的含义,例如 binary +
的行为方式不同数字和字符串 - 数字已添加,而字符串连接。)
对象可以实现(除此之外)这些模拟数字类型函数(方法):
__pos__(self) # called for unary +
__neg__(self) # called for unary -
__invert__(self) # called for unary ~
所以+object
与object.__pos__()
相同 - 它们是可互换的。
然而+object
更容易被人看到。
特定对象的创造者可以随心所欲地实现这些功能 - 正如其他人在现实世界中所展示的那样。
我的贡献 - 作为一个笑话: ++i != +i
in C / C ++ 。