字典
介紹
字典是“鍵值對(duì)”的無序可變序列,字典中的每個(gè)元素都是一個(gè)“鍵值對(duì)”,包含:“鍵對(duì)象”和“值對(duì)象”。
可以通過“鍵對(duì)象”實(shí)現(xiàn)快速獲取、刪除、更新對(duì)應(yīng)的“值對(duì)象”
字典特點(diǎn):
無序, 可變, 大括號(hào) {} + 鍵值對(duì) k,v
字典是 Python 項(xiàng)目中最常用的序列類型之一, 對(duì)應(yīng)Java 中常用的 Json 數(shù)據(jù)類型
操作
字典的創(chuàng)建
通過 {} + kv
來創(chuàng)建
通過dict()來創(chuàng)建字典對(duì)象(兩種方式)
過zip()創(chuàng)建字典對(duì)象
通過fromkeys創(chuàng)建值為空的字典
字典(類比Json)
“鍵”是任意的不可變數(shù)據(jù),比如:整數(shù)、浮點(diǎn)數(shù)、字符串、元組. 但是:列表、字典、集合這些可變對(duì)象,不能作為“鍵”.
并且“鍵”不可重復(fù)。
#“值”可以是任意的數(shù)據(jù),并且可重復(fù)
1. 通過{} 創(chuàng)建字典
a = {'name': 'TimePause',
'age': 18, 'sex': 'man'}
print(a)
2. 通過dict()來創(chuàng)建字典對(duì)象(兩種方式)
b =
dict(name='TimePause', age=18, sex='man')
a = dict([("name", "TimePause"),
("age", 18)])
print(b)
print(a)
c = {} # 空的字典對(duì)象
d = dict() #
空的字典對(duì)象
print(c)
print(d)
3. 通過zip()創(chuàng)建字典對(duì)象
k = ["name", "age",
"sex"]
v = ["TimePause", 18, "man"]
d = dict(zip(k, v))
print(d) #
{'name': 'TimePause', 'age': 18, 'sex': 'man'}
4. 通過fromkeys創(chuàng)建值為空的字典
f =
dict.fromkeys(["name", "age", "sex"])
print(f) # {'name': None, 'age': None,
'sex': None}
元素的訪問:
字典元素的訪問
a = {'name': 'TimePause', 'age': 18, 'sex': 'man'}
1. 通過
[鍵] 獲得“值”。若鍵不存在,則拋出異常。
b = a["name"]
print(b)
#c = a["birthday"]
KeyError: 'birthday'
#print(c)
2. 通過get()方法獲得“值”. 推薦使用.
優(yōu)點(diǎn)是:指定鍵不存在,返回None;也可以設(shè)定指定鍵不存在時(shí)默認(rèn)返回的對(duì)象. 推薦使用get()獲取“值對(duì)象”
b =
a.get("name")
c = a.get("birthday")
d = a.get("birthday",
"值不存在")
print(b)
print(c)
print(d)
3. 列出所有的鍵值對(duì)
b =
a.items()
print(b) # dict_items([('name', 'TimePause'), ('age', 18), ('sex',
'man')])
4. 列出所有的鍵,列出所有的值
k = a.keys()
v = a.values()
print(k, v)
dict_keys(['name', 'age', 'sex']) dict_values(['TimePause', 18, 'man'])
-
len() 鍵值對(duì)的個(gè)數(shù)
b = len(a)
print(b)
6. 檢測(cè)一個(gè)“鍵”是否在字典中
print("name"
in a) # True
字典元素添加、修改、刪除
- 給字典新增“鍵值對(duì)”。如果“鍵”已經(jīng)存在,則覆蓋舊的鍵值對(duì);如果“鍵”不存在,則新增“鍵值對(duì)
a =
{'name': 'TimePause', 'age': 18, 'sex': 'man'}
a['name'] =
"時(shí)間靜止"
a['phone'] = 18322222222
print(a)
- 使用 update()
將新字典中所有鍵值對(duì)全部添加到舊字典對(duì)象上。如果 key 有重復(fù),則直接覆蓋
a = {'name': 'TimePause', 'age': 18,
'sex': 'man'}
b = {'name': '時(shí)間靜止', 'age': 18, 'phone':
18322222222}
a.update(b) # 舊字典.update(新字典)
print(a)
- 字典中元素的刪除,可以使用
del() 方法;或者 clear() 刪除所有鍵值對(duì); pop() 刪除指定鍵值對(duì),并返回對(duì)應(yīng)的“值對(duì)象
a = {'name':
'TimePause', 'age': 18, 'sex': 'man'}
del (a["name"])
print(a) # {'age':
18, 'sex': 'man'}
a.pop("age")
print(a) # {'sex': 'man'}
popitem() :以后入先出的方式刪除和返回該鍵值對(duì)
#刪除并返回一個(gè)(鍵,值)對(duì)作為 2 元組。對(duì)以 LIFO(后進(jìn)先出)順序返回。如果 dict
為空,則引發(fā) KeyError。
a = {'name': 'TimePause', 'age': 18, 'sex':
'man'}
a.popitem()
print("第一次調(diào)用popitem",
a)
a.popitem()
print("第二次調(diào)用popitem",
a)
a.popitem()
print("第三次調(diào)用popitem", a)
#a.popitem() # KeyError:
'popitem(): dictionary is empty'
#print("第四次調(diào)用popitem", a)
序列解包
序列解包可以用于元組、列表、字典。序列解包可以讓我們方便的對(duì)多個(gè)變量賦值
#序列解包
#序列解包可以用于元組、列表、字典。序列解包可以讓我們方便的對(duì)多個(gè)變量賦值
x, y, z = (20, 30, 10) #
變量
(a, b, c) = (9, 8, 10) # 元組
[m, n, p] = [10, 20, 30] # 列表
序列解包用于字典時(shí),默認(rèn)是對(duì)“鍵”進(jìn)行操作;
a = {'name': 'TimePause', 'age': 18, 'sex':
'man'}
name, age, sex = a
print(name)
如果需要對(duì)鍵值對(duì)操作,則需要使用items()
name, age, sex = a.items()
print(name)
如果需要對(duì)“鍵”進(jìn)行操作,則需要使用keys()
name, age, sex = a.keys()
print(name)
如果需要對(duì)“值”進(jìn)行操作,則需要使用values()
name, age, sex = a.values()
print(name)
18
表格數(shù)據(jù)使用字典和列表存儲(chǔ)訪問
#表格數(shù)據(jù)使用字典和列表存儲(chǔ)訪問
#定義字典對(duì)象
a1 = {"name": "才子隊(duì)", "season": 1, "winner":
"比爾"}
a2 = {"name": "九頭蛇隊(duì)", "season": 2, "winner": "皮爾斯"}
a3 = {"name":
"巨亨隊(duì)", "season": 3, "winner": "卡羅爾"}
#定義列表對(duì)象tl
tl = [a1, a2,
a3]
print(tl)
print(tl[1].get("name"))
#輸出所有獲勝人員名稱
for x in
range(3):
print(tl[x].get("winner"))
#打印表的所有數(shù)據(jù)
for i in
range(len(tl)):
print(tl[i].get("name"), tl[i].get("season"),
tl[i].get("winner"))
字典核心底層原理(重要)
一
: 將一個(gè)鍵值對(duì)放進(jìn)字典的底層過程
字典對(duì)象的核心是散列表. 散列表是一個(gè)稀疏數(shù)組(總是有空白元素的數(shù)組)
數(shù)組的每個(gè)單元叫做 bucket. 每個(gè) bucket
有兩部分:一個(gè)是鍵對(duì)象的引用,一個(gè)是值對(duì)象的引用
由于所有 bucket 結(jié)構(gòu)和大小一致,我們可以通過偏移量來讀取指定bucket
下面操作將一個(gè)鍵值對(duì)放入字典
假設(shè)字典a對(duì)象創(chuàng)建完后,數(shù)組長(zhǎng)度為8
a =
{}
a["name"]="比爾"
我們要把”name”=”比爾”這個(gè)鍵值對(duì)放到字典對(duì)象a中,
首先第一步需要計(jì)算鍵”name”的散列值。Python中可以通過hash()來計(jì)算。
下面我們通過
Python Console 來查看 name 的hash值
bin(hash("name"))
'-0b1010111101001110110101100100101'
由于數(shù)組長(zhǎng)度為8,我們可以拿計(jì)算出的散列值的最右邊3位數(shù)字作為偏移量,即“101”,十進(jìn)制是數(shù)字5。
我們查看偏移量6對(duì)應(yīng)的bucket是否為空
如果為空,則將鍵值對(duì)放進(jìn)去。如果不為空,則依次取右邊3位作為偏移量,即“100”,十進(jìn)制是數(shù)字4
再查看偏移量為7的bucket是否為空。直到找到為空的bucket將鍵值對(duì)放進(jìn)去.
流程圖如下:
字典擴(kuò)容
python會(huì)根據(jù)散列表的擁擠程度擴(kuò)容?!皵U(kuò)容”指的是:創(chuàng)造更大的數(shù)組,將原有內(nèi)容拷貝到新數(shù)組中。
接近2/3時(shí),數(shù)組就會(huì)擴(kuò)容
二. 根據(jù)鍵查找“鍵值對(duì)”的底層過程
通過 Python console() 查看字典元素值如下
a.get("name")
'比爾'
1
2
當(dāng)調(diào)用a.get(“name”),就是根據(jù)鍵“name”查找到“鍵值對(duì)”,從而找到值對(duì)象“比爾”。
我們?nèi)匀灰紫扔?jì)算“name”對(duì)象的散列值:
bin(hash("name"))
'-0b1010111101001110110101100100101'
1
2
和存儲(chǔ)的底層流程算法一致,也是依次取散列值的不同位置的數(shù)字。
假設(shè)數(shù)組長(zhǎng)度為8,我們可以拿計(jì)算出的散列值的最右邊3位數(shù)字作為偏移量,即
101 ,十進(jìn)制是數(shù)字5。
我們查看偏移量5,對(duì)應(yīng)的 bucket 是否為空。如果為空,則返回 None 。
如果不為空,則將這個(gè) bucket
的鍵對(duì)象計(jì)算對(duì)應(yīng)散列值,和我們的散列值進(jìn)行比較,
如果相等。則將對(duì)應(yīng)“值對(duì)象”返回。
如果不相等,則再依次取其他幾位數(shù)字,重新計(jì)算偏移量。依次取完后,仍然沒有找到。則返回None
。
流程圖如下:
用法總結(jié):
字典在內(nèi)存中開銷巨大 (空間換時(shí)間)
鍵查詢速度很快
(通過位運(yùn)算+Hash運(yùn)算)
往字典里面添加新鍵值對(duì)可能導(dǎo)致擴(kuò)容,導(dǎo)致散列表中鍵的次序變化。
因此,不要在遍歷字典的同時(shí)進(jìn)行字典的修改
鍵必須可散列
數(shù)字、字符串、元組,都是可散列的
如果是自定義對(duì)象,
需要支持下面三點(diǎn):
(1) 支持 hash() 函數(shù) (2) 支持通過 eq () 方法檢測(cè)相等性 (3) 若 a==b 為真,則
hash(a)==hash(b) 也為真
-
編程
+關(guān)注
關(guān)注
88文章
3565瀏覽量
93536 -
字符串
+關(guān)注
關(guān)注
1文章
575瀏覽量
20468 -
元素
+關(guān)注
關(guān)注
0文章
47瀏覽量
8410 -
python
+關(guān)注
關(guān)注
55文章
4767瀏覽量
84375
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論