昨天看《核心程式設計》發現了一個鮮為人知的知識點,在Python中的字典比較和列表比較的策略竟然不相同,下面做具體分析。
字典比較原則
例子
1 2 3 4 5 6 7 |
>>> dict1 = {} >>> dict2 = {'host':'earth','port':80} >>> cmp(dict1, dict2) -1 >>> dict1['host'] = 'earth' >>> cmp(dict1,dict2) -1 |
第一個比較中,dict1比dict2小,因為dict2有更多的元素(2個vs.0個)。在向dict1新增一個元素後,dict1仍然比dict2小(2個vs.1個),雖然新增的元素在dict2中也存在。
1 2 3 4 5 6 |
>>> dict1['port'] = 8080 >>> cmp(dict1, dict2) 1 >>> dict1['port'] = 80 >>> cmp(dict1, dict2) 0 |
在向dict1新增第二個元素後,兩個字典的長度相同,所以用鍵比較大小。這時鍵相等,則通過它們的值比較大小。鍵’host’的值相同,對於鍵’port’,dict1中值比dict2中的值大(8080 vs. 80)。當把dict2中’port’的值設成和dict1中的值一樣,那麼兩個字典相等:它們有相同的大小、相同的鍵、相同的值,所以cmp()返回值是0。
1 2 3 4 5 6 |
>>> dict1['port'] = 'tcp' >>> cmp(dict1, dict2) 1 >>> dic2['port'] = 'udp' >>> cmp(dict1,dict2) -1 |
當向兩個字典中的仍和一個新增新元素時,這個字典馬上會成為大的那個字典,就像例子中的dict1一樣。向dict2新增鍵-值對後,因為兩個字典的長度又相等了,會繼續比較它們的鍵和值。
1 2 3 4 5 6 7 8 |
>>> cdict = {'fruits':1} >>> ddict = {'fruits':1} >>> cmp(cdict,ddict) 0 >>> cdict['oranges'] = 0 >>> ddict['apples'] = 0 >>> cmp(cdict, ddict) 14 |
上面的例子表明cmp()可以返回除-1、0、1外的其他值。
字典比較總結
字典比較的演算法按照以下順序進行:
(1)比較字典長度
如果字典的長度不同,那麼用 cmp(dict1, dict2) 比較大小時,如果字典 dict1 比 dict2 長,cmp()返回正值,如果 dict2 比 dict1 長,則返回負值。也就是說,字典中的鍵的個數越多,這個字典就越大,即:
len(dict1) > len(dict2) ==> dict1 > dict2
(2)比較字典的鍵
如果兩個字典的長度相同,那就按字典的鍵比較;鍵比較的順序和 keys()方法返回鍵的順序相同。 (注意: 相同的鍵會對映到雜湊表的同一位置,這保證了對字典鍵的檢查的一致性。) 這時,如果兩個字典的鍵不匹配時,對這兩個(不匹配的鍵)直接進行比較。當 dict1 中第一個不同的鍵大於 dict2 中第一個不同的鍵,cmp()會返回正值。
(3)比較字典的值
如果兩個字典的長度相同而且它們的鍵也完全匹配,則用字典中每個相同的鍵所對應的值進行比較。一旦出現不匹配的值,就對這兩個值進行直接比較。若 dict1 比 dict2 中相同的鍵所對應的值大,cmp()會返回正值。
(4)完全匹配
到此為止,即,每個字典有相同的長度、相同的鍵、每個鍵也對應相同的值,則字典完全匹配,返回 0 值。
列表比較原則
例子
1 2 3 4 5 6 7 8 9 10 11 12 |
>>> list1,list2 = [123,'xyz'],[456,'abc'] >>> cmp(list1, list2) -1 >>> >>> cmp(list2, list1) 1 >>> list3 = list2 + [789] >>> list3 [456,'abc',789] >>> >>> cmp(list2,list3) -1 |
當我們比較list1和list2時,list1和list2逐項比較。第一個比較操作發生在兩個列表的第一個元素之間,比如說,123與456比較,因為123如果比較的值相等,那麼兩個序列的下一個值繼續比較,知道不相等的情況出現,或者到達較短的一個序列的末尾。在這種情況下,長的序列被認為是較大的。這就是為什麼上面list2元組型別的比較也是用這種演算法。
列表比較總結
列表比較的演算法按照以下順序進行:
(1)對兩個列表的元組進行比較
(2)如果比較的元素是同型別的,則比較其值,返回結果。
(3)如果兩個元素不是同一種型別,則檢查他們是否是數字。
1 2 3 |
a.如果是數字,執行必要的數字強制型別轉換,然後比較。 b.如果有一方的元素是數字,則另一方的元素“大”(數字是“最小的”)。 c.否則,通過型別名字的字母順序進行比較。 |
(4)如果有一個列表首先到達末尾,則另一個長一點的列表“大”。
(5)如果我們用盡了兩個列表的元素而且所有的元素都是相等的,那麼結果就是個平局,就是說返回一個0。
總結
列表(元組)的比較原則:先大小後長短。
字典的比較原則:先長短,再鍵,再值。
參考來源
《Python核心程式設計(第二版)》