Python中的defaultdict方法

字典(dictionary)是Python中一種經常使用的數據類型。不一樣於其餘由數字索引的序列,字典是用"鍵"(key)來索引的。一般表示爲dict(key: val, ...),有如下特徵:html

  • 鍵能夠是任何不可變(immutable)數據類型,如數字,字符串和僅包含不可變數據類型的元組
  • 每一個鍵必須是惟一的
  • 字典中每一項的順序是任意的

1. KeyError異常

在Python中若是訪問字典裏不存在的鍵,會出現KeyError異常。有些時候,字典中每一個鍵都存在默認值是很方便的,例以下面的例子:python

>>> bag = ['apple', 'orange', 'cherry', 'apple',
...        'apple', 'cherry', 'blueberry'}]
>>> count = {}
>>> for fruit in bag:
...     count[fruit] += 1
...
Traceback (most recent call last):
    File "<stdin>", line 2, in <module>
KeyError: 'apple'

上例統計列表bag中單詞出現次數,並記錄在字典count中。單詞沒出現一次,count中對應的鍵值會增長一。可是在實習運行代碼時,每當單詞第一次被統計就會出現'KeyError'異常,這是由於它並不在字典count中,Python中dict對象並不存在默認值。app


2. 使用判斷語句檢查

所以,在單詞第一次被統計時,須要在count中給每一個鍵設定一個默認值1,這能夠用一個判斷語句來實現:ide

>>> for fruit in bag:
...     if fruit not in count:    #若是不存在,添加
...             count[fruit] = 1
...     else:
...             count[fruit] += 1
...
>>> count
{'apple': 3, 'blueberry': 1, 'orange': 1, 'cherry': 2}

3. 使用dict.setdefault()方法

dict.setdefault(key[,default])方法接受兩個參數,第一個是鍵的名稱,第二個參數是默認值。在調用時若是鍵存在字典中,會返回它的值;若是不存在,則會自動把它添加進字典中並返回默認值,default的默認值爲None。此外,default的值還能夠是列表,元組,集合和字典等。函數

>>> d = {'a': 1, 'b': 2}
>>> d.setdefault('a')    #鍵存在並返回他的值
1
>>> d.setdefault('c', 3)     #添加鍵-值
3
>>> d.setdefault('d')    #只添加鍵,默認值爲None
>>> d
{'a': 1, 'b': 2, 'c': 3, 'd': None}

接下來用它來實現上一個例子:學習

>>> count = {}
>>> for fruit in bag:
...     count.setdefault(fruit, 0)
...     count[fruit] += 1
...
>>> count
{'apple': 3, 'orange': 1, 'cherry': 2, 'blueberry': 1}

或者更簡潔一些:ui

>>> for fruit in bag:
...     count[fruit] = count.setdefault(fruit, 0) + 1

4. 使用collections.defaultdict類

class collections.defaultdict([default_factory[, ...]])

defaultdict是Python內建dict類的一個子類,第一個參數爲default_factory屬性提供初始值,默認爲None。它覆蓋一個方法並添加一個可寫實例變量。它的其餘功能與dict相同,但會爲一個不存在的鍵提供默認值,從而避免KeyError異常。以前例子的實現以下:this

>>> from collections import defaultdict
>>> count = defaultdict(int)
>>> for fruit in bag:
...     count[fruit] += 1
...
>>> count
defaultdict(<class 'int'>, {'apple': 3, 'orange': 1, 'cherry': 2, 'blueberry': 1})

4.1. 類型名稱做爲初始化函數參數

首先它能夠接受類型名稱來做爲初始化函數的參數,好比以前的例子中以int類名稱做爲參數。除了標準dict操做,它還支持__missing__(key)方法,經過參考官方文檔,它的機制以下:.net

若是default_factoryNone,會拋出以key爲參數的KeyError異常。翻譯

>>> d = defaultdict()    #default_factory爲None
>>> d['eric']
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
KeyError: 'eric'

若是default_factory不爲None, 此處原文爲:

" It is called without arguments to provide a default value for the given key, this value is inserted in the dictionary for the key, and returned."。
大概翻譯了下:它會在不接收任何參數的狀況下被調用,來爲給定的鍵提供默認值,這個值會被添加進字典並被返回。
>>> d = defaultdict(list)    #default_factory是列表名稱
>>> d['eric']    #訪問一個不存在的鍵
[]            #添加並返回默認值(一個空列表)
>>> d
defaultdict(<class 'list'>, {'eric': []})

由於defaultdictdict的一個子類,事實上訪問一個不存在的鍵時,dict類中的__getitem__方法會調用子類中__missing__()方法(但它不能直接被dict的實例調用),而且返回或拋出__missing__()方法所返回的值和拋出的異常。所以,若是調用default_factory引起一個異常,該異常傳播不變(propagated unchanged)。

請注意除__getitem__()以外的任何操做都不會調用__missing __()。 這意味着像正常的字典同樣,get()將返回None做爲默認值,而不是使用default_factory。

另外,還能夠給字典中的鍵映射多個值,具體方法是把多個值儲存在另外一個容器裏(如列表,元組,字典等)。是否使用列表或集合的選擇取決於預期用途:使用列表來保存每一項的插入順序;若是要消除重複的項(不關心順序),可使用元組。

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> for i in [1,2,3]:
...     d['eric'].append(i)
...
>>> d
defaultdict(<class 'list'>, {'eric': [1, 2, 3]})

>>> d['amy'] = {}
>>> d['amy']['a'] = 1
>>> d
defaultdict(<class 'list'>, {'eric': [1, 2, 3], 'amy': {'a': 1}})

能夠看出,給定默認值的類型以後並不意味着字典中全部值都必須是此類型,也能夠是其餘類型。還能使用相應的方法來對行操做,如列表的appendpop等方法。

4.2. 可調用函數做爲初始化函數參數

除了接受類型名稱做爲初始化函數的參數以外,還可使用任何不帶參數的可調用函數,並以該函數返回值做爲默認值。例如,定義函數zero()讓默認值爲0:

>>> from collections import defaultdict
>>> def zero():
...     return 0
...
>>> d = defaultdict(zero)
>>> d['eric']
0
>>> d
defaultdict(<function zero at 0x100662e18>, {'eric': 0})

或者使用lambda函數:

>>> d = defaultdict(lambda: 0)
>>> d['amy']
0
>>> d
defaultdict(<function <lambda> at 0x1019d3d90>, {'amy': 0})

須要注意的是, defaultdict接受的參數必須是可調用的。若直接傳遞數字0,就會出現TyptError的異常。

>>> d = defaultdict(0)
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
TypeError: first argument must be callable or None

聲明:

文章僅供學習及參考,禁止轉載。

參考:
相關文章
相關標籤/搜索