Какова цель унарного оператора + (pos) в Python?
Вообще говоря, что должен делать унарный +
в Python?
Я спрашиваю, потому что до сих пор я никогда не видел такой ситуации:
+obj != obj
Где obj
- общий объект, реализующий __pos__()
.
Итак, мне интересно: почему существуют +
и __pos__()
? Можете ли вы представить пример реального мира, в котором выражение выше оценивается как True
?
Ответы
Ответ 1
Вот пример "реального мира" из пакета 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')
Ответ 2
Я полагаю, что операторы Python, вдохновленные C, где для симметрии был введен оператор +
(а также некоторые полезные хаки, см. комментарии).
В слабо типизированных языках, таких как PHP или Javascript, + сообщает исполняемой среде об увеличении значения переменной в число. Например, в Javascript:
+"2" + 1
=> 3
"2" + 1
=> '21'
Python строго типизирован, поэтому строки не работают как числа и, как таковые, не реализуют унарный оператор plus.
Конечно, возможно реализовать объект, для которого + obj!= obj:
>>> class Foo(object):
... def __pos__(self):
... return "bar"
...
>>> +Foo()
'bar'
>>> obj = Foo()
>>> +"a"
Что касается примера, для которого это действительно имеет смысл, проверьте
сюрреалистические номера. Это надмножество реалов, которое включает
бесконечно малые значения (+ эпсилон, - эпсилон), где epsilon
положительное значение, меньшее любого другого положительного числа, но
больше 0; и бесконечные (+ бесконечность, - бесконечность).
Вы можете определить epsilon = +0
и -epsilon = -0
.
Пока 1/0
по-прежнему undefined, 1/epsilon = 1/+0
есть +infinity
и 1/-epsilon
= -infinity
. это
не более, чем принимать пределы 1/x
как x
aproaches 0
справа (+) или слева (-).
Поскольку 0
и +0
ведут себя по-разному, имеет смысл, что 0 != +0
.
Ответ 3
В 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
Ответ 4
Для симметрии, поскольку унарный минус является оператором, унарный плюс тоже должен быть. В большинстве арифметических ситуаций он ничего не делает, но имейте в виду, что пользователи могут определять произвольные классы и использовать эти операторы для чего угодно, даже если они не являются строго алгебраическими.
Я знаю, что это старый поток, но я хотел расширить существующие ответы, чтобы предоставить более широкий набор примеров:
-
+
может утверждать для положительности и исключать исключение, если это не так - очень полезно обнаруживать угловые случаи.
- Объект может быть многозначным (подумайте
±sqrt(z)
как единый объект - для решения квадратичных уравнений для разномасштабных аналитических функций, где угодно, где вы можете "свернуть" двоякую функцию в одну ветвь со знаком, включая ± 0, упомянутый vlopez.
- Если вы делаете ленивую оценку, это может создать объект функции, который добавляет что-то к тому, что он применяется к чему-то другому. Например, если вы постепенно увеличиваете арифметику.
- Как функция идентификации, которая передается в качестве аргумента для некоторого функционала.
- Для алгебраических структур, где знак накапливает - лестничные операторы и т.д. Конечно, это можно сделать с помощью других функций, но можно было бы увидеть нечто вроде
y=+++---+++x
. Более того, им не нужно ездить на работу. Это создает свободную группу плюсов и минусов, которые могут быть полезны. Даже в формальных реализациях грамматики.
- Дикое использование: оно может "пометить" шаг в вычислении как "активный" в некотором смысле. система reap/sow - каждый плюс запоминает значение, и в конце вы можете собрать собранные промежуточные продукты... потому что почему бы и нет?
Это, плюс все причины приведения типов, упомянутые другими.
И в конце концов... приятно иметь еще один оператор, если он вам нужен.
Ответ 5
__pos__()
существует в Python, чтобы дать программистам аналогичные возможности, как в языке C++
, - перегрузить операторы, в этом случае унарный оператор +
.
(Перегрузочные операторы означают, что они имеют различное значение для разных объектов, например, двоичный +
ведет себя по-разному для чисел, а для строк - числа добавляются при объединении строк.)
Объекты могут реализовывать (помимо других) эти эмулятивные числовые типы функций (методов):
__pos__(self) # called for unary +
__neg__(self) # called for unary -
__invert__(self) # called for unary ~
Итак, +object
означает то же самое, что и object.__pos__()
- они взаимозаменяемы.
Однако +object
легче на глаза.
Создатель конкретного объекта имеет свободные руки для реализации этих функций, как он хочет - как показали другие люди в своих реальных примерах.
И мой вклад - как шутка: ++i != +i
в C/С++.