[Python] Tuple 與整數值的大小比較?
之前遇過一次 [Python] None 與整數值的大小比較? 的問題,
沒想到今天又遇到一次類似的…
Python 2 在處理不同型別之間的大小比較時,真的很容易踩雷…
這次的雷是什麼呢?
我們會將 (priority, task) 這樣的 tuple 塞進 PriorityQueue,
而這個 priority 本身又是一個 (priority_value, task_id) 的 tuple,
所以理論上,priority_value (整數值) 越小的就會優先從 queue 中取出,
如果 priority_value 一樣,就是 task_id (整數值) 越小的就會優先從 queue 中取出。
上面的定義沒什麼問題,
但是程式裡在某些地方,不小心把 priority 設成只有 priority_value,
也就是可能會有 priority_value 和 (priority_value, task_id) 比較大小的狀況。
比較一個整數值和 tuple,大小怎麼算呢?
查了一下,在 Python 3 中,不同型別比較大小是會有 exception 的。
但在 Python 2 中,則是依照「型別名稱」來比較大小…
這邊是 Learning Python, 4th edition 的節錄:
Comparisons of differently typed objects (e.g., a string and a list) work — the language defines a fixed ordering among different types, which is deterministic, if not aesthetically pleasing. That is, the ordering is based on the names of the types involved: all integers are less than all strings, for example, because “int” is less than “str”.
因為整數的型別是 “int”,tuple 的型別是 “tuple”,
“int” < “tuple”,所以整數永遠小於 tuple。
這會導致什麼問題呢?
就算我們有一組 priority tuple (1, task_id),
它和 priority integer (9) 比也是輸,因為整數 (9) 比 tuple (1, task_id) 要小…
來做個實驗吧~
先定義一組正常的 priority tuple (5, 1) 和 (5, 2):
>>> class A(object): pass ... >>> a = A() >>> b = A() >>> pa = (5, 1) >>> pb = (5, 2)
這兩個 tuple 因為 priority_value 都是 5,
因此接著比較 task_id 1 和 2,結果正常:
>>> (pa, a) < (pb, b) True
接著把 pa 從 tuple 改成整數值 5:
>>> pa = (5) >>> type(pa) <type 'int'> >>> type(pb) <type 'tuple'>
這時候再做比較,因為 pa 是整數,pb 是 tuple,
因此 pa 一定小於 pb:
>>> (pa, a) < (pb, b) True
把 pa 的值調成比 pb 裡的第一個值要大,結果一樣:
>>> pa = 6 >>> (pa, a) < (pb, b) True
把 pa 的值調成比 pb 裡的第一個值要小,結果也是一樣:
>>> pa = 1 >>> (pa, a) < (pb, b) True
嗯… 真的要很小心,該是 tuple 的地方就得是 tuple 啊…
參考資料:Comparing None with built-in types using arithmetic operators?