Python_6_內(nèi)置結(jié)構(gòu)-字典

1. 字典介紹

??在 Python 中字典屬于一種映射類型剃袍,它和 set 相同酬凳,同樣屬于非線性結(jié)構(gòu),Python 官方對(duì) dict 有如下解釋:

  • 一個(gè)映射對(duì)象映射一個(gè)可 hash 的值到任意一個(gè)對(duì)象上去。
  • 映射是可變的對(duì)象。
  • dict 是當(dāng)前唯一一個(gè)標(biāo)準(zhǔn)的映射類型矾利。
  • 字典的鍵幾乎可以是任意的值。
  • 字典的值不必可 hash,也就是說值可以是列表憔杨,字典,或者其他任意可變的對(duì)象
  • 如果 key 相同蒜胖,那么后面的 value 將會(huì)覆蓋先前的 value
  • 不建議使用 float 類型作為字典的 key

??簡(jiǎn)單來說:字典是由 key:value 鍵值對(duì)組成的數(shù)據(jù)的集合消别,它的主要特點(diǎn)是 可變的無序的翠勉、不重復(fù)的妖啥。

字典的 key 必須是可 hash 對(duì)象,之所以快对碌,因?yàn)槠浔举|(zhì)上是 用空間換時(shí)間

2. 字典的基本操作

??字典是除集合 (set) 以外另一種可變的非線性容器模型蒿偎,在 Python 中非常強(qiáng)大朽们,適合各種結(jié)構(gòu)數(shù)據(jù)的存儲(chǔ)、嵌套等诉位。

2.1. 字典的定義

??字典的每個(gè) key 與 value 的鍵值對(duì)用冒號(hào) : 分割骑脱,每對(duì)之間用逗號(hào) , 分割,整個(gè)字典包括在花括號(hào) { } 中苍糠。例:{'a':1, 'b':2}叁丧,Python 提供了多種創(chuàng)建字典的方式,如下:

  • 基本格式:d = dict() 或者 d = {}
  • dict(**kwargs):使用 name=value 對(duì)岳瞭,來初始化一個(gè)字典
  • dict(iterable, **kwargs):使用可迭代對(duì)象和 name=value 構(gòu)造字典拥娄,注意 可迭代對(duì)象必須是一個(gè)二元結(jié)構(gòu)
  • dict(mapping, **kwargs): 使用一個(gè)字典構(gòu)造另一個(gè)字典
  • dic = {'a':1, 'b':2, 'c':3, 'd':[1,2,3]}
  • dic = dict.fromkeys(iterable, value): 使用可迭代對(duì)象的值作為 key 生成字典,value 默認(rèn)為 0瞳筏,否則用指定的 value 對(duì)字典進(jìn)行初始化稚瘾。
In : d1=dict()

In : d2={}

In : d3 = dict(a=1, b=2) ; d3 
Out: {'a': 1, 'b': 2}

In : d4 = dict([('a', 1),('b', 2)], c=3, d=4) ; d4
Out: {'a': 1, 'b': 2, 'c': 3, 'd': 4}

In : d5 = dict(d4, e=5, f=6) ; d5
Out: {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}

In : d7 = dict.fromkeys(range(5)) ; d7
Out: {0: None, 1: None, 2: None, 3: None, 4: None}

In : d8 = dict.fromkeys(range(5), 100) ; d8 
Out: {0: 100, 1: 100, 2: 100, 3: 100, 4: 100} 

2.2. 字典元素的訪問

??有如下三種方式訪問字典的鍵值對(duì):

  1. d[key]:返回 key 對(duì)應(yīng)的 value,key 不存在拋出 KeyError 異常
  2. dict.get(key[, default]):返回 key 對(duì)應(yīng)的 value姚炕,key 不存在返回缺省值摊欠,如果沒有設(shè)置缺省值返回 None
  3. dict.setdefault(key[, default]):返回 key 對(duì)應(yīng)的值 value,key 不存在柱宦,添加 key:value 鍵值對(duì)(value 設(shè)置為 default)些椒,并返回 value,如果 default 沒有設(shè)置缺省為 None
In : dic = {'a':1, 'b':2, 'c':3, 'd':4}

In : dic['a']
Out: 1

In : dic['e']   # 不存在 'e' 這個(gè) key掸刊,所以直接訪問會(huì)出現(xiàn)異常
---------------------------------------------------------------------------
KeyError                                  Traceback(most recent call last)
<ipython-input-34-87d22c709971> in <module>
----> 1 dic['e']

KeyError: 'e'

In : dic.get('a')     # key 存在免糕,則返回對(duì)應(yīng)的值
Out: 1

In : dic.get('e')     # 不存在,默認(rèn)會(huì)返回 None,ipython 優(yōu)化了 None 的輸出说墨,所以這里無顯示

In : dic.get('e', 'not exist')     # 不存在時(shí)骏全,由指定的 default 進(jìn)行返回
Out: 'not exist'

In : dic.setdefault('a', 'ok')   # 設(shè)置 a 的值為 ok,a 存在,所以返回 a 對(duì)應(yīng)的值 1
Out: 1

In : dic.setdefault('e', 'ok')   # 設(shè)置 e 的值為 ok尼斧,e 不存在姜贡,所以設(shè)置并返回 value(key 不存在時(shí)等同于設(shè)置并訪問了)
Out: 'ok'

In : dic
Out: {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 'ok'}

當(dāng)然字典也可以被迭代訪問,后面介紹

2.3. 字典的增刪改

??由于字典可變棺棵、非線性楼咳、無序的特性,而且字典的 key 必須是可 hash 的對(duì)象烛恤,查找某個(gè) key 也是直接 hash()母怜,然后找到對(duì)應(yīng)的位置的,所以我們對(duì)它某個(gè) key 的修改可以理解為是時(shí)間復(fù)雜度 O(1) 的操作缚柏,效率很高苹熏,主要有以下幾種方法。

  • d[key] = value: 將 key 對(duì)應(yīng)的值修改為 value币喧,key 不存在添加新的 key:value 對(duì)轨域。
  • dic.update([other]) --> None: 使用另一個(gè)字典的 k,v 對(duì)更新本字典,key 不存在時(shí)添加杀餐,存在時(shí)則覆蓋干发,所以不會(huì)返回新的字典,屬于原地修改史翘。
  • dic.pop(key[, default]): key 存在枉长,移除它,并返回它的 value琼讽,key 不存在返回指定的 default必峰,如果 default 未指定,那么會(huì)返回 KeyError 異常跨琳。
  • dic.popitem(): 移除并返回一個(gè)任意的鍵值對(duì)自点,字典為 empty 時(shí),拋出 KeyError 異常脉让。
  • dic.clear(): 清空字典桂敛。
  • del dic['a']: 通用的刪除變量方法。
In : dic = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 'ok'}

In : dic['a'] = 1000 ; dic
Out: {'a': 1000, 'b': 2, 'c': 3, 'd': 4, 'e': 'ok'}

In : dic2 = {'a':200,'f':50} ; dic.update(dic2) ; dic
Out: {'a': 200, 'b': 2, 'c': 3, 'd': 4, 'e': 'ok', 'f': 50}

In : dic.pop('a')             # 彈出一個(gè) key'a'溅潜,key 存在返回 key 對(duì)應(yīng)的 value
Out: 200

In : dic
Out: {'b': 2, 'c': 3, 'd': 4, 'e': 'ok', 'f': 50}

In : dic.pop('g')              # 彈出一個(gè) key'g'术唬,key 不存在,又沒有指定 default滚澜,則會(huì)報(bào) KeyError 異常
---------------------------------------------------------------------------
KeyError                                  Traceback(most recent call last)
<ipython-input-49-311c3ba80251> in <module>
----> 1 dic.pop('g')

KeyError: 'g'

In : dic.pop('g','not exist')       # 指定了 default粗仓,當(dāng) key 不存在時(shí),會(huì)返回指定的 default 值 
Out: 'not exist'

In : dic.popitem()          # 彈出一個(gè) key:valyue 鍵值對(duì),返回對(duì)象是元組形式
Out:('d', 4)

In : dic
Out: {'b': 2, 'c': 3, 'e': 'ok', 'f': 50}

In : del dic['e'] ; dic
Out: {'b': 2, 'c': 3, 'f': 50}

In : dic.clear()

In : dic
Out: {}

??當(dāng)我們以字典的某個(gè)對(duì)象比如 keys,values,items 等為條件對(duì)字典進(jìn)行遍歷時(shí)借浊,我們不能在遍歷的同時(shí)刪除字典的元素塘淑,字典在運(yùn)行時(shí)不允許長(zhǎng)度改變,但是在 list 中這種操作是可以的蚂斤,但是會(huì)得到意想不到的結(jié)果存捺,建議對(duì)容器進(jìn)行遍歷的同時(shí)不要修改它的長(zhǎng)度。

In : s = {'a': 1, 'b': 2, 'c': 4, 'd': 5, 'e': 7, 'j': 10}

In : len(s)  
Out: 6

In : for i in range(6): 
...:     s.popitem() 
...:

In : s  
Out: {}

# 下面這種方式是錯(cuò)的曙蒸,也是絕對(duì)不可以的捌治。
In : for i in s.keys():
...:     s.pop(i)
...:
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-35-9c51f70f750a> in <module>
----> 1 for i in s.keys():
      2     s.pop(i)
      3

RuntimeError: dictionary changed size during iteration

3. 字典遍歷

??在 Python 中,我們所說的基本數(shù)據(jù)結(jié)構(gòu):字符串纽窟、元組肖油、列表,集合臂港,包括字典森枪,都可以認(rèn)為是一個(gè)容器箱子,只要是容器审孽,我們就可以進(jìn)行遍歷(是否有序和是否可以遍歷沒有必然關(guān)系疲恢,只不過有序的話是順序拿出,而無序則是隨機(jī)拿出)瓷胧,我們可以使用多種方式對(duì)字典進(jìn)行迭代遍歷,但是有些地方和其他類型不同棚愤。

3.1. 遍歷字典的 key

??dic.keys(): --> dict_keys --> 返回字典 dic 的所有 key 組成的一個(gè) dict_keys 視圖集合(類 set 結(jié)構(gòu)搓萧,不會(huì)生成新的內(nèi)存空間)。

In : dic = {'a':1, 'b':2, 'c':3, 'd':4}

In : for key in dic: 
...:     print(key)
...:
a
d
c
b

In : for key in dic.keys(): 
...:     print(key)
...:
a
d
c
b

In : dic.keys()
Out: dict_keys(['a', 'd', 'c', 'b'])

??迭代字典就是在迭代字典的 key宛畦,所以直接迭代字典和使用字典的 keys() 方法返回一個(gè) keys 的視圖然后再迭代瘸洛,是一樣的效果。

3.2. 遍歷字典的 value

??dic.values(): --> dict_values --> 返回字典 dic 的所有 values 組成的一個(gè) dict_values 視圖集合(類 set 結(jié)構(gòu)次和,不會(huì)生成新的內(nèi)存空間)反肋。

In : for i in dic: 
...:     print(dic[i])
...:
1
2
3
4

In : for i in dic.values(): 
...:     print(i)
...:
1
2
3
4

In : dic.values()  
Out: dict_values([1, 2, 3, 4])

??可以首先遍歷字典的 key,然后再通過 key 來訪問對(duì)應(yīng)的 value踏施,也可以通過 dic.values() 直接訪問 values石蔗。

3.3. 變量字典的鍵值對(duì)

??dic.items(): --> dict_items :返回字典 dic 的所有的 key 和 value(每個(gè) key 和 value 的鍵值對(duì)由元組表示) 組成的一個(gè) dict_items 視圖集合(類 set 結(jié)構(gòu),不會(huì)生成新的內(nèi)存空間)畅形。

In : for i in dic.items(): 
...:     print(i) 
...:
('a', 1)
('b', 2)
('c', 3)
('d', 4)

In : for key,value in dic.items(): 
...:     print('key:{} value:{}'.format(key,value)) 
...:
key:a value:1
key:b value:2
key:c value:3
key:d value:4

??由于返回的每個(gè)鍵值對(duì)為元組格式养距,那么利用我們前面學(xué)的封裝與解構(gòu),可以很方便的獲取 key 和它對(duì)應(yīng)的 value

3.4. 字典遍歷小結(jié)

??在 Python3 中日熬,keys棍厌、values、items 方法返回一個(gè)類似生成器的可迭代對(duì)象,不會(huì)把函數(shù)的返回結(jié)果復(fù)制到內(nèi)存空間中耘纱。

  • Dictionary view 對(duì)象敬肚,可以使用 len()、iter()束析、in 操作
  • 字典的 entry 的動(dòng)態(tài)視圖艳馒,字典變化,視圖將反映出這些變化
  • keys 返回一個(gè)類似 set 的對(duì)象畸陡,也可以看作是一個(gè) set 集合鹰溜,如果 values 可 hash 的話,那么 items 也可以看作是類 set 對(duì)象

??Python 2 中丁恭,keys曹动、values、items 方法會(huì)返回一個(gè)新的列表牲览,占據(jù)新的內(nèi)存空間墓陈,所以 Python 2 建議使用 iterkeys、itervalues第献、iteritems贡必,返回一個(gè)迭代器,而不是返回一個(gè) copy

[11:20:32 python@centos7 ~]$ python
Python 2.7.5(default, Oct 30 2018, 23:45:53) 
[GCC 4.8.5 20150623(Red Hat 4.8.5-36)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> s = {'a':1,'b':2}
>>> s.keys()    # 直接生成一個(gè) keys 的列表
['a', 'b']
>>> s.iterkeys()   # 對(duì)象庸毫,迭代可以獲取數(shù)據(jù)
<dictionary-keyiterator object at 0x7f271c5fa520>

4. defaultdict 默認(rèn)值字典

??defaultdit object 是 dict 的子類仔拟,我們稱它為默認(rèn)值字典,即在創(chuàng)建字典時(shí)給所有的 value 指定一個(gè)默認(rèn)值飒赃,它存放在 collections 模塊中利花,使用前需要先進(jìn)行導(dǎo)入。為什么有默認(rèn)值字典這種類型呢载佳?請(qǐng)看如下代碼:

dic = {}
for i in 'abacdabeddfef':
    if i not in dic:     # 這句其實(shí)也可以優(yōu)化為 dic[i] = dic.get(i, 0) + 1
        dic[i] = 0
    dic[i] += 1
print(dic)

# 結(jié)果:
{'a': 3, 'b': 2, 'c': 1, 'd': 3, 'e': 2, 'f': 2}

??我們?cè)谟?jì)算一個(gè)字符串或者一個(gè)列表中的元素重復(fù)的次數(shù)時(shí)炒事,通常會(huì)用到字典對(duì)齊進(jìn)行計(jì)數(shù),如果元素不存在字典中蔫慧,那么就需要初始化元素挠乳,當(dāng)我們使用默認(rèn)值字典時(shí),就可以優(yōu)化的更簡(jiǎn)潔姑躲。
??當(dāng) key 不存在時(shí)睡扬,返回的是工廠函數(shù)的默認(rèn)值,比如 list 對(duì)應(yīng) [ ]肋联,str 對(duì)應(yīng)的是空字符串威蕉,set 對(duì)應(yīng) set( ),int 對(duì)應(yīng) 0

from collections import defaultdict
dic = defaultdict(int)   # defaultdict(lambda :0)  這種方法也可以設(shè)置默認(rèn)為 0
for i in 'abacdabeddfef':
    dic[i] += 1    # 默認(rèn)是 int 型橄仍,可以直接加減
print(dic)

# 結(jié)果:
defaultdict(<class 'int'>, {'a': 3, 'b': 2, 'c': 1, 'd': 3, 'e': 2, 'f': 2})

5. OrderedDict 有序字典

??Ordered dictionaries 像一個(gè)有序字典韧涨,但是它記住的是插入元素的順序牍戚。當(dāng)我們迭代有序字典時(shí),它會(huì)按照這些鍵值對(duì)插入的順序返回虑粥。它同樣存在于 collections 模塊中如孝,需要使用時(shí)請(qǐng)先導(dǎo)入。

In : from collections import OrderedDict

In : dic = OrderedDict()  

In : dic = dic.fromkeys('abc', 1) ; dic
Out: OrderedDict([('a', 1),('b', 1),('c', 1)])

In : for k,v in dic.items():     # 按照插入的順序
...:     print(k, v) 
...:
a 1
b 1
c 1

In : dic = dict([('a', 1),('b', 1),('c', 1)])  

In : for k,v in dic.items():    # 無序的
...:     print(k, v) 
...:
a 1
c 1
b 1

??注意:在 3.6 的版本的 python/ipython 解釋器中娩贷,直接迭代或者打印時(shí)第晰,是有序的(OrderedDict),但是在 3.5 版本以前都是隨機(jī)的彬祖,千萬不要以為字典是有序的茁瘦!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市储笑,隨后出現(xiàn)的幾起案子甜熔,更是在濱河造成了極大的恐慌,老刑警劉巖突倍,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腔稀,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡羽历,警方通過查閱死者的電腦和手機(jī)焊虏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秕磷,“玉大人诵闭,你說我怎么就攤上這事∨煜” “怎么了涂圆?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)币叹。 經(jīng)常有香客問我,道長(zhǎng)模狭,這世上最難降的妖魔是什么颈抚? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮嚼鹉,結(jié)果婚禮上贩汉,老公的妹妹穿的比我還像新娘。我一直安慰自己锚赤,他們只是感情好匹舞,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著线脚,像睡著了一般赐稽。 火紅的嫁衣襯著肌膚如雪叫榕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天姊舵,我揣著相機(jī)與錄音晰绎,去河邊找鬼。 笑死括丁,一個(gè)胖子當(dāng)著我的面吹牛荞下,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播史飞,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼尖昏,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了构资?” 一聲冷哼從身側(cè)響起抽诉,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蚯窥,沒想到半個(gè)月后掸鹅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拦赠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年巍沙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荷鼠。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡句携,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出允乐,到底是詐尸還是另有隱情矮嫉,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布牍疏,位于F島的核電站蠢笋,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏鳞陨。R本人自食惡果不足惜昨寞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望厦滤。 院中可真熱鬧援岩,春花似錦、人聲如沸掏导。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽趟咆。三九已至添瓷,卻和暖如春梅屉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仰坦。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工履植, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人悄晃。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓玫霎,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親妈橄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子庶近,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容