2011-11-18 82 views
8

我習慣於在Python中看到if obj is None:,最近我遇到了if obj is():。由於元組不可變,所以在Python解釋器中這聽起來像是一個合理的內部優化,使空元組成爲一個單元,因此允許使用is而不是要求==。但這是保證某個地方?自從哪個版本的翻譯?將對象與Python 2中的'is'運算符進行比較。

問題很重要,因爲如果()不是單身人士,並且有一種生成具有不同地址的空元組的方法,則使用is {}是一個錯誤。如果只有在x> 0的Python 2.x後才能保證,那麼如果需要確保代碼的向後兼容性,那麼知道x的值很重要。同樣重要的是要知道這是否可以使用時pypy /的Jython/IronPython的破壞你的代碼...

+0

這絕對不地道。有沒有合理的用例呢? –

+0

@StevenRumbalski:沒有特殊用例。我發現代碼使用這個,它讓我想知道我是否應該改回它,或者更新我對「is」操作符的看法。在解釋器級別實現()作爲單例是有意義的... –

回答

11

從Python 2 docs和Python 3 docs

...空元組的兩次出現的可能或可能不產生相同的對象。

換句話說,你不能指望() is()評估爲真。

0

讓我們用id()方法得到的()內部ID:

>>> id(()) 
140180995895376 
>>> empty_tuple =() 
>>> id(empty_tuple) 
140180995895376  # same as the id of() 
>>> from copy import copy 
>>> id(copy(empty_tuple)) 
140180995895376  # still the same as the id of() 

它看起來像()被有效地存儲爲Python中的單例(至少在python> 2.6中)。

""空字符串變量的行爲相同。

+0

只是出於好奇,'[]'怎麼樣? – Toomai

+0

這個例子沒有證明什麼:它沒有顯示在2個不同模塊中創建的2個空元組將在最後成爲相同的對象。字面字符串是在Python中實現的(早在2.x分支時就是這種情況),而空字符串也可能是單例,但是沒有證據表明你看到的並不是實習的副作用。 –

+0

@Toomai:列表是可變的,所以你不能讓空列表成爲單例。 –

0

這是CPython當前版本的非保證實現細節,因此您不一定能夠在其他Python實現中依賴它,包括Jython,IronPython,PyPy以及可能的未來版本的CPython。

使用is對大名單進行比較時顯得約0.04 μ運行更快我的系統上:

$ python -m timeit -s "x = range(10000)" "x is()" 
10000000 loops, best of 3: 0.0401 usec per loop 

$ python -m timeit -s "x = range(10000)" "x ==()" 
10000000 loops, best of 3: 0.0844 usec per loop 

當然也可能是相當糟糕的,如果你對某事比較自定義__eq__()方法:

$ python -m timeit -s $'import time\nclass X(object):\n def __eq__(self, other): return time.sleep(1)\nx = X()' "x ==()" 
10 loops, best of 3: 1e+03 msec per loop 

不過,如果這種效率差異很關鍵,我認爲這會指向一個設計問題。

0

這不是關於優化。這是關於對象比較。 Python「is」用於測試對象身份,然後比較空元組「()」不需要使用「==」運算符。事實上,Python中的任何東西都可以與「is」進行比較。

>>> obj =() 
>>> obj is() 
True 
>>> isinstance(obj, tuple) 
True 
>>> obj is tuple 
False 
>>> type(obj) is tuple 
True 
>>> type(()) 
<type 'tuple'> 
>>> type(tuple) 
<type 'type'> 
>>> tuple == type(()) # value comparison with == 
True 

同樣爲任何其他值:

>>> 333 is int 
False 
>>> type(333) is int 
True 
>>> isinstance(333, int) 
True 
+1

但是比較執行'a = 257'和'b = 257'語句。 'a是b'可以返回'False'。 –

+0

是的。但是這與python內部相關,因爲id(a)可能與id(b)不同。類型(a)是類型(b)allways返回True。我試圖證明「is」操作符更適合鍵入比較,但實例對象也可以進行比較。 –

+0

優秀的點:身份應該比較類型時工作。但在這種情況下,'isinstance()'通常是正確的選擇。 –

相關問題