[Python] Tuple 與整數值的大小比較?

[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?

 

 

(本頁面已被瀏覽過 1,055 次)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料