[英]What's the purpose of the + (pos) unary operator in Python?
一般來說,Python中的一元+
應該做什么?
我問是因為到目前為止,我從未見過這樣的情況:
+obj != obj
其中obj
是實現__pos__()
的通用 object 。
所以我想知道:為什么+
和__pos__()
存在? 你能提供一個真實的例子,上面的表達式計算為True
嗎?
這是來自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')
在 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
我相信 Python 運算符的靈感來自 C,其中引入了+
運算符以實現對稱(還有一些有用的技巧,請參閱注釋)。
在弱類型語言(如 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; 和無窮大(+無窮大,-無窮大)。
您可以定義epsilon = +0
和-epsilon = -0
。
雖然1/0
仍未定義,但1/epsilon = 1/+0
是+infinity
,而1/-epsilon
= -infinity
。 當x
從右邊 (+) 或從左邊 (-) 趨近0
,它只不過是取1/x
極限。
由於0
和+0
行為不同,因此0 != +0
是有道理的。
對於對稱,因為一元減號是一個運算符,所以一元加號也必須是。 在大多數算術情況下,它不做任何事情,但請記住,用戶可以定義任意類並將這些運算符用於他們想要的任何東西,即使它不是嚴格的代數。
我知道這是一個舊線程,但我想擴展現有答案以提供更廣泛的示例:
+
可以斷言肯定性,如果不是,則拋出異常 - 對於檢測極端情況非常有用。±sqrt(z)
視為單個對象——用於求解二次方程、多分支分析函數、任何可以將雙值函數“折疊”為帶有符號的分支的任何東西。這包括 ±0 vlopez 提到的案例。y=+++---+++x
這樣的東西。 更重要的是,他們不必通勤。 這構建了一組可能有用的免費加號和減號。 即使在正式的語法實現中。那,加上其他人提到的所有類型轉換原因。
畢竟……如果您需要的話,再多一個操作員就好了。
這里的很多例子看起來更像是錯誤。 不過,這實際上是一個功能:
+
運算符意味着一個副本。這在為標量和數組編寫通用代碼時非常有用。
例如:
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
......我想那會起作用,但它很麻煩。
Unary +
是一個非常好的選擇。
__pos__()
存在於Python 中,為程序員提供與C++
語言類似的可能性——重載運算符,在這種情況下是一元運算符+
。
(重載運算符意味着為不同的對象賦予它們不同的含義,例如二進制+
對數字和字符串的行為不同——在連接字符串時添加數字。)
對象可以實現(除其他之外)這些模擬數字類型的函數(方法):
__pos__(self) # called for unary +
__neg__(self) # called for unary -
__invert__(self) # called for unary ~
所以+object
與object.__pos__()
意思相同——它們可以互換。
然而, +object
更容易被人看到。
特定對象的創建者可以自由地按照自己的意願實現這些功能——正如其他人在他們現實世界的例子中所展示的那樣。
還有我的貢獻——開個玩笑: ++i != +i
in C/C++ 。
一元+
實際上是查看值是否為數字的最快方法(如果不是則引發異常)! 它是字節碼中的一條指令,其中諸如 isinstance(i, int) 之類的東西實際上查找並調用了isinstance
函數!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.