[英]What's the purpose of the + (pos) unary operator in Python?
Generally speaking, what should the unary +
do in Python?一般来说,Python中的一元
+
应该做什么?
I'm asking because, so far, I have never seen a situation like this:我问是因为到目前为止,我从未见过这样的情况:
+obj != obj
Where obj
is a generic object implementing __pos__()
.其中
obj
是实现__pos__()
的通用 object 。
So I'm wondering: why do +
and __pos__()
exist?所以我想知道:为什么
+
和__pos__()
存在? Can you provide a real-world example where the expression above evaluates to True
?你能提供一个真实的例子,上面的表达式计算为
True
吗?
Here's a "real-world" example from the decimal
package:这是来自
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')
In Python 3.3 and above, collections.Counter
uses the +
operator to remove non-positive counts.在 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})
So if you have negative or zero counts in a Counter
, you have a situation where +obj != obj
.因此,如果
Counter
有负数或零计数,则会出现+obj != obj
。
>>> obj = Counter({'a': 0})
>>> +obj != obj
True
I believe that Python operators where inspired by C, where the +
operator was introduced for symmetry (and also some useful hacks, see comments).我相信 Python 运算符的灵感来自 C,其中引入了
+
运算符以实现对称(还有一些有用的技巧,请参阅注释)。
In weakly typed languages such as PHP or Javascript, + tells the runtime to coerce the value of the variable into a number.在弱类型语言(如 PHP 或 Javascript)中,+ 告诉运行时将变量的值强制转换为数字。 For example, in Javascript:
例如,在 Javascript 中:
+"2" + 1
=> 3
"2" + 1
=> '21'
Python is strongly typed, so strings don't work as numbers, and, as such, don't implement an unary plus operator. Python 是强类型的,因此字符串不能用作数字,因此不实现一元加号运算符。
It is certainly possible to implement an object for which +obj != obj :当然可以实现一个 +obj != obj 的对象:
>>> class Foo(object):
... def __pos__(self):
... return "bar"
...
>>> +Foo()
'bar'
>>> obj = Foo()
>>> +"a"
As for an example for which it actually makes sense, check out the surreal numbers .至于实际有意义的示例,请查看超现实数字。 They are a superset of the reals which includes infinitesimal values (+ epsilon, - epsilon), where epsilon is a positive value which is smaller than any other positive number, but greater than 0;
它们是实数的超集,包括无穷小的值 (+ epsilon, - epsilon),其中 epsilon 是一个正值,它小于任何其他正数,但大于 0; and infinite ones (+ infinity, - infinity).
和无穷大(+无穷大,-无穷大)。
You could define epsilon = +0
, and -epsilon = -0
.您可以定义
epsilon = +0
和-epsilon = -0
。
While 1/0
is still undefined, 1/epsilon = 1/+0
is +infinity
, and 1/-epsilon
= -infinity
.虽然
1/0
仍未定义,但1/epsilon = 1/+0
是+infinity
,而1/-epsilon
= -infinity
。 It is nothing more than taking limits of 1/x
as x
aproaches 0
from the right (+) or from the left (-).当
x
从右边 (+) 或从左边 (-) 趋近0
,它只不过是取1/x
极限。
As 0
and +0
behave differently, it makes sense that 0 != +0
.由于
0
和+0
行为不同,因此0 != +0
是有道理的。
For symmetry, because unary minus is an operator, unary plus must be too.对于对称,因为一元减号是一个运算符,所以一元加号也必须是。 In most arithmetic situations, it doesn't do anything, but keep in mind that users can define arbitrary classes and use these operators for anything they want, even if it isn't strictly algebraic.
在大多数算术情况下,它不做任何事情,但请记住,用户可以定义任意类并将这些运算符用于他们想要的任何东西,即使它不是严格的代数。
I know it's an old thread, but I wanted to extend the existing answers to provide a broader set of examples:我知道这是一个旧线程,但我想扩展现有答案以提供更广泛的示例:
+
could assert for positivity and throw exception if it's not - very useful to detect corner cases. +
可以断言肯定性,如果不是,则抛出异常 - 对于检测极端情况非常有用。±sqrt(z)
as a single object -- for solving quadratic equations, for multibranched analytical functions, anything where you can "collapse" a twovalued function into one branch with a sign. This includes the ±0 case mentioned by vlopez.±sqrt(z)
视为单个对象——用于求解二次方程、多分支分析函数、任何可以将双值函数“折叠”为带有符号的分支的任何东西。这包括 ±0 vlopez 提到的案例。y=+++---+++x
.y=+++---+++x
这样的东西。 Even more, they don't have to commute. That, plus all the typecasting reasons mentioned by others.那,加上其他人提到的所有类型转换原因。
And after all... it's nice to have one more operator in case you need it.毕竟……如果您需要的话,再多一个操作员就好了。
A lot of examples here look more like bugs.这里的很多例子看起来更像是错误。 This one is actually a feature, though:
不过,这实际上是一个功能:
+
operator implies a copy . +
运算符意味着一个副本。 This is extremely useful when writing generic code for scalars and arrays.这在为标量和数组编写通用代码时非常有用。
For example:例如:
def f(x, y):
z = +x
z += y
return z
This function works on both scalars and NumPy arrays without making extra copies and without changing the type of the object and without requiring any external dependencies!此功能上都标量和NumPy的阵列工作未做额外的副本并没有改变对象的类型,而无需任何外部依赖!
If you used numpy.positive
or something like that, you would introduce a NumPy dependency, and you would force numbers to NumPy types, which can be undesired by the caller.如果您使用
numpy.positive
或类似的东西,您将引入 NumPy 依赖项,并且您将强制数字为 NumPy 类型,这可能是调用者不希望的。
If you did z = x + y
, your result would no longer necessarily be the same type as x
.如果你做了
z = x + y
,你的结果将不再一定是与x
相同的类型。 In many cases that's fine, but when it's not, it's not an option.在许多情况下这很好,但如果不是,则不是一种选择。
If you did z = --x
, you would create an unnecessary copy, which is slow.如果你做了
z = --x
,你会创建一个不必要的副本,这很慢。
If you did z = 1 * x
, you'd perform an unnecessary multiplication, which is also slow.如果你做了
z = 1 * x
,你会执行一个不必要的乘法,这也很慢。
If you did copy.copy
... I guess that'd work, but it's pretty cumbersome.如果你做了
copy.copy
......我想那会起作用,但它很麻烦。
Unary +
is a really great option for this. Unary
+
是一个非常好的选择。
__pos__()
exists in Python to give programmers similar possibilities as in C++
language — to overload operators , in this case the unary operator +
. __pos__()
存在于Python 中,为程序员提供与C++
语言类似的可能性——重载运算符,在这种情况下是一元运算符+
。
( Overloading operators means give them a different meaning for different objects , eg binary +
behaves differently for numbers and for strings — numbers are added while strings are concatenated .) (重载运算符意味着为不同的对象赋予它们不同的含义,例如二进制
+
对数字和字符串的行为不同——在连接字符串时添加数字。)
Objects may implement (beside others) these emulating numeric types functions (methods):对象可以实现(除其他之外)这些模拟数字类型的函数(方法):
__pos__(self) # called for unary +
__neg__(self) # called for unary -
__invert__(self) # called for unary ~
So +object
means the same as object.__pos__()
— they are interchangeable.所以
+object
与object.__pos__()
意思相同——它们可以互换。
However, +object
is more easy on the eye.然而,
+object
更容易被人看到。
Creator of a particular object has free hands to implement these functions as he wants — as other people showed in their real world's examples.特定对象的创建者可以自由地按照自己的意愿实现这些功能——正如其他人在他们现实世界的例子中所展示的那样。
And my contribution — as a joke: ++i != +i
in C/C++ .还有我的贡献——开个玩笑:
++i != +i
in C/C++ 。
Unary +
is actually the fastest way to see if a value is numeric or not (and raise an exception if it isn't)!一元
+
实际上是查看值是否为数字的最快方法(如果不是则引发异常)! It's a single instruction in bytecode, where something like isinstance(i, int) actually looks up and calls the isinstance
function!它是字节码中的一条指令,其中诸如 isinstance(i, int) 之类的东西实际上查找并调用了
isinstance
函数!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.