Generally speaking, what should the unary +
do in Python?
I\'m asking because, so far, I have never seen a situation like this:
+obj !=
__pos__()
exists in Python to give programmers similar possibilities as in C++
language — to overload operators, in this case the unary operator +
.
(Overloading operators means give them a different meaning for different objects, e. g. 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.
However, +object
is more easy on the eye.
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++.
In Python 3.3 and above, collections.Counter uses the +
operator to remove non-positive counts.
>>> 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
.
>>> 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).
In weakly typed languages such as PHP or Javascript, + tells the runtime to coerce the value of the variable into a number. For example, in 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.
It is certainly possible to implement an object for which +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; and infinite ones (+ infinity, - infinity).
You could define epsilon = +0
, and -epsilon = -0
.
While 1/0
is still undefined, 1/epsilon = 1/+0
is +infinity
, and 1/-epsilon
= -infinity
. It is
nothing more than taking limits of 1/x
as x
aproaches 0
from the right (+) or from the left (-).
As 0
and +0
behave differently, it makes sense that 0 != +0
.
Here's a "real-world" example from the decimal
package:
>>> 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')
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!
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.
If you did z = x + y
, your result would no longer necessarily be the same type as 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.
If you did z = 1 * x
, you'd perform an unnecessary multiplication, which is also slow.
If you did copy.copy
... I guess that'd work, but it's pretty cumbersome.
Unary +
is a really great option for this.
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.y=+++---+++x
. Even more, they don't have to commute. This constructs a free group of plus and minuses which could be useful. Even in formal grammar implementations.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.