Python字典101-Dictionary就該這麼進

字典術語:Dict-Mapping;Item-Entry

字典英文成爲Dict或者Dictionary,也稱作mapping。
Python中,字典是有任意個元素組成的集合,每個元素成爲一個Item,也成爲Entry。key+value組合構成了Item,即Entry。

Python字典的初始化

初始化方法一:dict(**kwargs),使用dict[name]=value完成字典的初始化
初始化方法二:dict(iterable,**kwarg),使用可迭代對象加dict[name]=value初始化字典,注意,這裏的iterable可迭代對象的元素必須是一個二元機構
初始化方法三:dict(mapping,**kwarg),使用字典構造另一個字典

d1 = {}

官方推薦了幾種寫法:

>>> a = dict(one=1, two=2, three=3)
>>> b = {'one': 1, 'two': 2, 'three': 3}
>>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
>>> d = dict([('two', 2), ('one', 1), ('three', 3)])
>>> e = dict({'three': 3, 'one': 1, 'two': 2})
>>> a == b == c == d == e
True
#我們可以對照做練習:
dn = dict(a=100,b=200)
d4=dict(dn)
d5 = dict(d4, a=300, b=400)
d6=dict([('a',100),["b",200],(1,"abcde")],b=300,c=400)
print(dn)
print(d4)
print(d5)
print(d6)
{'a': 100, 'b': 200}
{'a': 100, 'b': 200}
{'a': 300, 'b': 400}
{'a': 100, 'b': 300, 1: 'abcde', 'c': 400}
b = {'one': 1, 'two': 2, 'three': 3}
b
{'one': 1, 'two': 2, 'three': 3}

類方法 dict.fromkeys(iterable, value):

d = dict.fromkeys(range(5))
d
{0: None, 1: None, 2: None, 3: None, 4: None}
d = dict.fromkeys(range(3),0)
d
{0: 0, 1: 0, 2: 0}

Python字典元素的訪問

len(d)

Return the number of items in the dictionary d.

d[key]

Return the item of d with key key. Raises a KeyError if key is not in the map.
這種方法,當key不存在時候就會返回KeyError

get(key[,default])

這種方法在key不存在時候,就不會返回KeyError了,而是可以返回一個默認的值。例如:

d.get(9,"返回默認值,並沒有設置哦")
'返回默認值,並沒有設置哦'
# 查看一下現在的d,確認返回值沒有被添加到字典裏
d
{0: 0, 1: 0, 2: 0}

setdefault(key,“設置的默認值”)

setdefault方法,當key不存在時候就添加鍵值對,value設置爲default,並且返回default;
如果default沒有設置,那麼缺省值我None。

d.setdefault(10,"設置默認的值")
'設置默認的值'
d # 對比d.get ,default的值設置進了字典d
{0: 0, 1: 0, 2: 0}

Python字典的刪除

pop(key[,default])

key存在就移除它,並返回它的value
key不存在,就返回給定的default
如果default沒有設置,那麼,key不存在時候就會報出KeyError異常錯誤

popitem()

移除並返回一個任意值的鍵值對
字典如果爲empty,則拋出KeyError異常

d.popitem()
(0, 0)

clear

清空字典

遍歷

1. 遍歷key

d = {}
for i in range(5):
    d[i]=i+10
    
d
{0: 10, 1: 11, 2: 12, 3: 13, 4: 14}
for k in d:
    print(k)
0
1
2
3
4
for k in d.keys():
    print(k)
0
1
2
3
4

2. 遍歷value

for v in d.values():
    print(v)
10
11
12
13
14
for k in d.keys():
    print(d[k])
    print(d.get(k))
10
10
11
11
12
12
13
13
14
14

遍歷字典的items

利用items方法把字典的鍵和值提取出來的方法

for item in d.items():
    print(item)
(0, 10)
(1, 11)
(2, 12)
(3, 13)
(4, 14)
for k,v in d.items():
    print(k,v)
0 10
1 11
2 12
3 13
4 14
for k,_ in d.items():
    print(k)
0
1
2
3
4
for _,k in d.items():
    print(k)
10
11
12
13
14

Python3中, keys, values, items方法返回一個類似一個生成器的可迭代對象

  • Dictionary view對象,可以使用len(), iter(), in操作
  • 字典的entry的動態的視圖,字典變化,視圖將反映出這些變化
  • keys返回一個類set對象,也就是可以看做一個set集合。如果values都可以hash,那麼items也可以看做是類set對象
    Python2中,上面的方法會返回一個新的列表,立即佔據新的內存空間。所以Python2建議使用
    iterkeys, itervalues, iteritems版本,返回一個迭代器,而不是返回一個copy

遍歷與刪除

d = dict(a = 10, b = 20, c = 30)
d
{'a': 10, 'b': 20, 'c': 30}

在刪除字典元素過程中,需要使用keys方法,這個過程不能改變字典的size,比如錯誤的做法:

for k,v in d.items():
    print(d.pop(k))  # 錯誤的做法,會引起size changed 異常
20



---------------------------------------------------------------------------

RuntimeError                              Traceback (most recent call last)

<ipython-input-39-67316909e7b7> in <module>
----> 1 for k,v in d.items():
      2     print(d.pop(k))  # 錯誤的做法


RuntimeError: dictionary changed size during iteration
# 這個方法就不會破壞字典的size,不過僅做說明只用,因爲這樣做就等效於clear
while len(d):
    print(d.popitem())
d
{}

key的理解

字典的key要求與set元素的要求是一致的:

  • set元素就可以看做key,可以把set理解爲dict的簡化版
  • hashable可哈希的纔可作爲key,所以在使用某對象作爲字典key之前,可以用hash做測試
  • 使用key訪問,就如同列表使用index一樣,時間複雜度是O(1),這是我們推薦使用的訪問元素的方式,例如:
d = {
    1:0,
    2.0:3,
    "digital":None,
    ("hello","sales","I"):"client",
    b"a":"334455"
}
d
{1: 0,
 2.0: 3,
 'digital': None,
 ('hello', 'sales', 'I'): 'client',
 b'a': '334455'}

Python字典有序性的理解

Python字典是按照key的hash值無序存儲的

但有時候我們需要一個有序的元素順序,在Python3.6之前,使用OrderedDict就可以實現;
到Python3.6開始dict自身支持元素按照生成的先後順序排序;
但是,3.6之後是否還會繼續支持dict按照生成順序排序呢?我們不確定,所以,建議還是按照不知道Python3.6的這個屬性學習和處理。

我們閒聊瞭解一下到底Python對無序數據結構記錄了什麼順序?

當我們使用Python3.5 的版本時候,Python 3.6之前,在不同的機器上,甚至同一個程序分別運行2次,都不能確定不同的key的先後順序。

C:\Python\Python353>python Python 3.5.3

d = {"a":100,"b":200, "c": 300, "d": 400}
print(d)

這個輸出結果不是固定的,有可能是:
{ ‘b’: 200,‘a’: 100, ‘c’: 300, ‘d’: 400}
也有可能是:
{ ‘b’: 200,‘a’: 100, ‘c’: 300, ‘d’: 400}

這時候我們需要使用OrderedDict模塊:

from collections import OrderedDict

orderd = OrderedDict()
orderd["b"] =200
orderd["c"] = 300
orderd["a"] = 100
orderd["d"] =400

print(orderd) # 這時候輸出結構就是按照輸入的順序
OrderedDict([('b', 200), ('c', 300), ('a', 100), ('d', 400)])

當然,Python3.6記錄了Python字典key的錄入順序,遍歷的時候,也是按照這個順序,例如下面的輸出結果一定是固定的,不會像Python3.5那樣變:

d = {"a":100,"b":200, "c": 300, "d": 400}
print(d)
{'a': 100, 'b': 200, 'c': 300, 'd': 400}

目前,建議不要3.6提供的這種字典特性,還是以爲字典返回的是無序的。如果非要這種有序,建議使 用OrderedDict。

defaultdict

Python字典的defaultdict其實就是實現給字典的key附默認的值,以下面的代碼爲例:當d1中k不存在的時候,先創建k和[]空列表鍵值對,然後爲列表增加元素。最後,得到{‘l’: [0, 1, 2], ‘o’: [0, 1, 2], ‘v’: [0, 1, 2], ‘e’: [0, 1, 2]}

d1 = {}
for k in 'love':
    for v in range(3):
        if k not in d1.keys():
            d1[k] = []
        d1[k].append(v)
print(d1)
{'l': [0, 1, 2], 'o': [0, 1, 2], 'v': [0, 1, 2], 'e': [0, 1, 2]}

Python提供了defaultdict默認的類,即defaultdict(default_factory)構造一個特殊字典,初始化是可以傳入一個工廠函數,當訪問一個不存在的key是,就會調用這個工廠函數獲得返回值,和key湊成鍵值對,例如:

from collections import defaultdict

d2 = defaultdict(list)
print(d2["a"]) #創建鍵值對
print(d2) # 這樣就發現獨立一個鍵值對
[]
defaultdict(<class 'list'>, {'a': []})
from collections import defaultdict

# d2 = defaultdict(list)
for k in "love":
    for v in range(3):
        d2[k].append(v) # 
print(d2)
defaultdict(<class 'list'>, {'l': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 0, 1, 2, 0, 1, 2, 0, 1, 2], 'o': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 0, 1, 2, 0, 1, 2, 0, 1, 2], 'v': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 0, 1, 2, 0, 1, 2, 0, 1, 2], 'e': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 0, 1, 2, 0, 1, 2, 0, 1, 2]})
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章