說說 Python 的映射數據類型

1 映射類關係

Python 的 collections.abc 模塊內擁有 Mapping 和 MutableMapping 這兩個抽象基類,它們爲 dict 和其他類似的類型提供了接口定義。

mutable /ˈmjuːtəbl/
adj.
Capable of or subject to change or alteration.

它們之間的類關係如下圖所示:

箭頭從子類指向父類,抽象類和抽象方法的名稱以斜體顯示。

首先是 Container、Iterable 與 Sized 三大接口,接着 Mapping 接口在繼承了前面三大接口的基礎上,又定義了一些自有接口。

這些接口定義了構建一個映射類型所需要的接口與方法。

2 判定映射類型

可以通過 isinstance() 方法來判定某個對象是不是廣義上的映射類型:

import collections
import logging

logging.basicConfig(level=logging.DEBUG, format='%(levelname)s - %(message)s')


my_dict = {}
result = isinstance(my_dict, collections.abc.Mapping)
logging.info('result -> %s', result)

運行結果:

INFO - result -> True

3 可散列的數據類型

Python 標準庫裏的所有映射類型都是利用 dict 來實現的,它們的鍵都必須是可散列的數據類型。

可散列的數據類型指的是:在這種數據類型對象的生命週期中,它的散列值是不變的。它會實現 __hash__() 方法與__qe__() 方法,後一種方法是用來與其他鍵做比較。如果兩個對象的散列值相等,那麼就可以判定這兩個對象相等。

原子不可變的數據類型(如:str、bytes 和數值類型)都是可散列數據類型。frozenset 中只能容納可散列類型,因此也是可散列數據類型。

frozenset() 會返回一個凍結的集合,凍結後集合不能再添加或刪除元素。

而元組比較特殊,只有當一個元組中所包含的元素都是可散列類型時,它纔是可散列的。Luciano Ramalho 舉了一個示例來說明這一點。

tt = (1, 2, (30, 40))
logging.info('hash(tt) -> %s', hash(tt))

tf = (1, 2, frozenset([30, 40]))
logging.info('hash(tf) -> %s', hash(tf))

tl = (1, 2, [30, 40])
logging.info('hash(tl) -> %s', hash(tl))

運行結果:

INFO - result -> True
INFO - hash(tt) -> 8027212646858338501
INFO - hash(tf) -> 985328935373711578
TypeError: unhashable type: 'list'

示例中可以看到:元組內包含了一個非散列的列表,就會拋出 TypeError 異常。

一般情況下,用戶自定義類型的對象都是可散列的,散列值就是這些對象 id() 函數的返回值,因此這些對象在比較的時候都是不相等的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章