Python字典創(chuàng)建、訪問、修改、刪除及遍歷的完整指南
在編程中,我們經(jīng)常需要建立一種“映射關(guān)系”:比如通過學(xué)號(hào)找到學(xué)生姓名,通過商品編號(hào)找到價(jià)格。Python 的字典(dict)正是為此而生。它是一種可變、無序(Python 3.7+ 保持插入順序)、鍵唯一的映射類型,通過哈希表實(shí)現(xiàn) O(1) 的平均查找速度。
1. 字典是什么?
字典是鍵值對(duì)(key-value pair)的集合。每個(gè)鍵對(duì)應(yīng)一個(gè)值,鍵必須是不可變類型(如字符串、數(shù)字、元組),值可以是任意類型。
# 一個(gè)簡(jiǎn)單的字典:學(xué)生信息
student = {"name": "張三", "age": 20, "major": "計(jì)算機(jī)"}
print(student["name"]) # 輸出:張三代碼解析:
student = {"name": "張三", "age": 20, "major": "計(jì)算機(jī)"}:創(chuàng)建一個(gè)名為student的字典,包含三個(gè)鍵值對(duì)。鍵"name"對(duì)應(yīng)值"張三",鍵"age"對(duì)應(yīng)整數(shù)20,鍵"major"對(duì)應(yīng)字符串"計(jì)算機(jī)"。print(student["name"]):通過方括號(hào)語法使用鍵"name"訪問其對(duì)應(yīng)的值,輸出"張三"。
核心特性:
- 鍵唯一:同一個(gè)字典中不能有重復(fù)的鍵。如果重復(fù)賦值,后一個(gè)會(huì)覆蓋前一個(gè)。
- 可變:可以增、刪、改鍵值對(duì)。
- 無序 → 有序:在 Python 3.6 之前是無序的,3.7 之后插入順序被保留(作為語言特性)。這意味著遍歷字典時(shí)會(huì)按照鍵值對(duì)添加的順序返回。
- 高效查找:基于哈希表,平均時(shí)間復(fù)雜度 O(1)。
C/C++ 聯(lián)動(dòng):
- C++ 中實(shí)現(xiàn)類似映射可以使用
std::unordered_map<Key, Value>(哈希表,平均 O(1))或std::map<Key, Value>(紅黑樹,O(log n))。Python 字典的底層就是哈希表,因此與unordered_map更相似。 - C++ 示例:
#include <unordered_map>
#include <string>
std::unordered_map<std::string, int> student = {{"name", 20}, {"age", 20}};
// 訪問:student["name"] 或 student.at("name")- 區(qū)別:Python 字典的鍵可以是任意不可變類型(如字符串、數(shù)字、元組),而 C++
unordered_map的鍵類型需要在編譯期確定,且必須提供哈希函數(shù)(內(nèi)置類型已提供)。
2. 創(chuàng)建字典
2.1 使用花括號(hào){}
# 空字典
empty = {}
# 帶初始值
person = {"name": "李四", "age": 25}代碼解析:
empty = {}:一對(duì)花括號(hào)創(chuàng)建了一個(gè)空字典。注意:空花括號(hào)是字典,不是集合(集合需要用set()創(chuàng)建空集)。person = {"name": "李四", "age": 25}:花括號(hào)內(nèi)用逗號(hào)分隔多個(gè)鍵值對(duì),每個(gè)鍵值對(duì)格式為"key": value。鍵可以是字符串、數(shù)字等不可變類型,值任意。
2.2 使用dict()構(gòu)造函數(shù)
# 從關(guān)鍵字參數(shù)創(chuàng)建
person = dict(name="王五", age=30)
# 從可迭代對(duì)象(如列表的元組對(duì))創(chuàng)建
items = [("name", "趙六"), ("age", 28)]
person = dict(items) # {'name': '趙六', 'age': 28}
# 空字典
empty = dict()代碼解析:
dict(name="王五", age=30):關(guān)鍵字參數(shù)形式,鍵名會(huì)被當(dāng)作字符串(不需要引號(hào)),這是創(chuàng)建字典的簡(jiǎn)潔方式。注意:鍵名必須是合法的變量名(不能以數(shù)字開頭,不能含空格)。dict(items):items是一個(gè)列表,每個(gè)元素是一個(gè)包含兩個(gè)元素的元組(或列表)。dict()將每個(gè)元組的第一個(gè)元素作為鍵,第二個(gè)作為值,構(gòu)造字典。dict():無參數(shù)調(diào)用創(chuàng)建一個(gè)空字典,與{}等效。
C/C++ 聯(lián)動(dòng):
- C++ 中初始化
unordered_map可以使用初始化列表:
std::unordered_map<std::string, int> person = {{"name", 30}, {"age", 25}};- 從鍵值對(duì)序列構(gòu)造:可以遍歷 vector 并插入,沒有 Python 的
dict(iterable)那樣直接。
2.3 使用zip()組合兩個(gè)序列
keys = ["a", "b", "c"]
values = [1, 2, 3]
d = dict(zip(keys, values)) # {'a': 1, 'b': 2, 'c': 3}代碼解析:
zip(keys, values):將兩個(gè)列表打包成一系列元組:[('a',1), ('b',2), ('c',3)]。dict(...):將這個(gè)元組列表轉(zhuǎn)換為字典。如果兩個(gè)序列長(zhǎng)度不同,zip會(huì)以較短的為準(zhǔn)。
2.4 字典推導(dǎo)式(見7 )
3. 訪問字典
3.1 通過鍵訪問([])
d = {"apple": 5, "banana": 3}
print(d["apple"]) # 5
# print(d["orange"]) # KeyError: 'orange'代碼解析:
d["apple"]:使用方括號(hào)和鍵名獲取對(duì)應(yīng)的值。如果鍵不存在,會(huì)拋出KeyError異常,程序終止(除非捕獲異常)。因此這種方法適合確定鍵一定存在的場(chǎng)景。
C/C++ 聯(lián)動(dòng):
- C++ 中
unordered_map的operator[]行為與 Python 不同:如果鍵不存在,它會(huì)插入一個(gè)默認(rèn)構(gòu)造的值并返回引用,不會(huì)拋出異常。例如:
std::unordered_map<std::string, int> d; int val = d["orange"]; // 插入鍵 "orange" 并值為 0,val = 0
- 若希望像 Python 一樣不插入新鍵,可以使用
d.find(key)或d.at(key)(at會(huì)拋出std::out_of_range)。
3.2 使用get()方法(安全訪問)
print(d.get("orange")) # None(不報(bào)錯(cuò))
print(d.get("orange", 0)) # 0(指定默認(rèn)值)代碼解析:
d.get("orange"):嘗試獲取鍵"orange"的值。如果鍵不存在,返回None(不會(huì)拋出異常)。適合不確定鍵是否存在的場(chǎng)景。d.get("orange", 0):第二個(gè)參數(shù)指定默認(rèn)值,當(dāng)鍵不存在時(shí)返回0而不是None。
C/C++ 聯(lián)動(dòng):C++ 中無直接對(duì)應(yīng)的 get 方法,通常使用 find 并檢查迭代器:
auto it = d.find("orange");
int val = (it != d.end()) ? it->second : 0;3.3 獲取所有鍵、值、鍵值對(duì)
d = {"a": 1, "b": 2}
print(d.keys()) # dict_keys(['a', 'b'])
print(d.values()) # dict_values([1, 2])
print(d.items()) # dict_items([('a', 1), ('b', 2)])代碼解析:
d.keys()、d.values()、d.items()返回的是視圖對(duì)象(view)。這些視圖動(dòng)態(tài)反映字典的變化,如果字典后續(xù)修改,視圖也會(huì)相應(yīng)改變。- 視圖對(duì)象支持迭代,可以用于
for循環(huán)。例如for k in d.keys():。 - 在 Python 3 中,視圖不是列表,但可以轉(zhuǎn)換為列表:
list(d.keys())。
C/C++ 聯(lián)動(dòng):C++ 中獲取所有鍵需要手動(dòng)遍歷或使用 range-based for:
for (const auto& pair : d) {
// pair.first 是鍵,pair.second 是值
}3.4 setdefault()—— 獲取值,若鍵不存在則設(shè)置默認(rèn)值
d = {"a": 1}
v = d.setdefault("b", 100) # 鍵 "b" 不存在,設(shè)置 d["b"]=100,并返回 100
print(d) # {'a': 1, 'b': 100}
v2 = d.setdefault("a", 99) # 鍵存在,返回原值 1,不修改代碼解析:
setdefault先檢查鍵是否存在,如果存在則返回對(duì)應(yīng)的值;如果不存在,則插入key: default鍵值對(duì),并返回default。這個(gè)方法常用于需要初始化缺失鍵的場(chǎng)景(比如構(gòu)建分組字典)。
C/C++ 聯(lián)動(dòng):C++ 中可以用 insert 配合 try_emplace 實(shí)現(xiàn)類似功能,但不如 Python 簡(jiǎn)潔。
4. 修改字典
4.1 添加或更新鍵值對(duì)
d = {}
d["name"] = "張三" # 添加
d["age"] = 25 # 添加
d["age"] = 26 # 更新代碼解析:
- 當(dāng)方括號(hào)內(nèi)的鍵不存在時(shí),該賦值操作會(huì)在字典中添加一個(gè)新的鍵值對(duì)。
- 當(dāng)鍵已存在時(shí),賦值會(huì)更新該鍵對(duì)應(yīng)的值。
C/C++ 聯(lián)動(dòng):C++ 中 unordered_map 的 operator[] 同樣可添加或更新,但區(qū)別在于:如果鍵不存在,會(huì)插入默認(rèn)構(gòu)造的值再賦值。例如 d["age"] = 25 會(huì)先檢查,若不存在則插入 int()(即0),再賦值為 25。因此 C++ 中不能直接用 [] 判斷是否存在。
4.2 update()—— 合并另一個(gè)字典或可迭代對(duì)象
d1 = {"a": 1, "b": 2}
d2 = {"b": 3, "c": 4}
d1.update(d2) # d1 變?yōu)?{'a': 1, 'b': 3, 'c': 4}
# 也支持關(guān)鍵字參數(shù):d1.update(c=5, d=6)代碼解析:
update()接受一個(gè)字典或鍵值對(duì)的可迭代對(duì)象(如列表的元組)。它會(huì)將參數(shù)中的每個(gè)鍵值對(duì)合并到原字典中,如果鍵已存在則覆蓋,如果不存在則添加。- 常見的用法:
d1.update(d2)相當(dāng)于for k, v in d2.items(): d1[k] = v。
C/C++ 聯(lián)動(dòng):C++ 中合并兩個(gè) unordered_map 需要循環(huán)插入,沒有直接方法。
5. 刪除字典元素
5.1 del語句
d = {"a": 1, "b": 2, "c": 3}
del d["b"] # 刪除鍵為 "b" 的項(xiàng)
# del d["x"] # KeyError 若鍵不存在代碼解析:
del d["b"]刪除字典中鍵為"b"的鍵值對(duì)。如果鍵不存在,拋出KeyError。del也可以刪除整個(gè)字典變量:del d,之后字典對(duì)象被回收。
5.2 pop()—— 刪除并返回指定鍵的值
value = d.pop("a") # 返回 1,d 變?yōu)?{'c': 3}
# d.pop("x") # KeyError
d.pop("x", None) # 不報(bào)錯(cuò),返回 None代碼解析:
pop(key)刪除指定鍵并返回對(duì)應(yīng)的值。如果鍵不存在,拋出KeyError。pop(key, default)提供默認(rèn)值,當(dāng)鍵不存在時(shí)返回default,不會(huì)拋出異常。
C/C++ 聯(lián)動(dòng):C++ 中 unordered_map 的 erase 方法刪除鍵并返回被刪除元素的數(shù)量(0或1),不返回值。要獲取值需先 find。
5.3 popitem()—— 刪除并返回最后一個(gè)鍵值對(duì)(Python 3.7+ 按 LIFO)
d = {"a": 1, "b": 2}
key, value = d.popitem() # 返回 ('b', 2)(插入順序的最后一個(gè))代碼解析:
- 在 Python 3.7+ 中,
popitem()刪除并返回字典中最后插入的鍵值對(duì)(后進(jìn)先出)。在 3.6 之前,由于字典無序,它返回任意一個(gè)鍵值對(duì)。 - 返回值為一個(gè)元組
(key, value),可直接拆包。
5.4 clear()—— 清空字典
d.clear() # {}代碼解析:刪除字典中所有鍵值對(duì),使字典變?yōu)榭兆值?nbsp;{}。
6. 遍歷字典
6.1 遍歷鍵
for key in d:
print(key)
# 或 for key in d.keys():代碼解析:直接使用 for key in d 是遍歷字典最常用的方式,每次迭代獲取一個(gè)鍵。也可以用 d.keys() 顯式獲取鍵視圖。
6.2 遍歷值
for value in d.values():
print(value)代碼解析:d.values() 返回值的視圖,用于遍歷所有值。注意:值可能重復(fù),且無法直接通過值找到對(duì)應(yīng)的鍵(除非反向查找)。
6.3 同時(shí)遍歷鍵和值
for key, value in d.items():
print(key, value)代碼解析:d.items() 返回鍵值對(duì)視圖,每個(gè)元素是一個(gè) (key, value) 元組。通過拆包可以直接獲取鍵和值。
6.4 帶條件或轉(zhuǎn)換的遍歷
# 只打印值大于 10 的項(xiàng)
for k, v in d.items():
if v > 10:
print(k, v)代碼解析:可以在循環(huán)體內(nèi)加入條件判斷,過濾出滿足條件的鍵值對(duì)。
7. 字典推導(dǎo)式
與列表推導(dǎo)式類似,用于快速生成字典。
# 平方映射
squares = {x: x**2 for x in range(5)} # {0:0, 1:1, 2:4, 3:9, 4:16}代碼解析:基本語法 {key_expr: value_expr for variable in iterable}。這里 x 是迭代變量,鍵是 x,值是 x**2。
# 條件過濾:只保留偶數(shù)鍵
even_squares = {x: x**2 for x in range(10) if x % 2 == 0}代碼解析:在推導(dǎo)式末尾加上 if 子句,只對(duì)滿足條件的 x 生成鍵值對(duì)。
# 交換鍵和值
original = {"a": 1, "b": 2}
inverted = {v: k for k, v in original.items()} # {1: 'a', 2: 'b'}代碼解析:遍歷原字典的 items(),將鍵和值互換作為新字典的鍵值對(duì)。注意:如果原字典有重復(fù)的值,后面的會(huì)覆蓋前面的,因?yàn)殒I必須唯一。
8. 嵌套字典
字典的值可以是另一個(gè)字典,用于表示層次化數(shù)據(jù)。
students = {
"S001": {"name": "Alice", "score": 85},
"S002": {"name": "Bob", "score": 92}
}
print(students["S001"]["name"]) # Alice代碼解析:
- 外層字典的鍵是學(xué)號(hào),值是一個(gè)內(nèi)層字典(包含
name和score)。 - 訪問時(shí)使用兩層方括號(hào):先通過學(xué)號(hào)獲取內(nèi)層字典,再通過
"name"獲取姓名。
安全訪問嵌套:逐層使用 get 或使用 try-except。
9. 字典的常用方法匯總
| 方法 | 說明 |
|---|---|
get(key, default) | 安全獲取值,鍵不存在時(shí)返回默認(rèn)值(默認(rèn) None)。 |
setdefault(key, default) | 如果鍵存在,返回其值;否則設(shè)置 d[key]=default 并返回 default。 |
update([other]) | 用另一個(gè)字典或鍵值對(duì)序列更新當(dāng)前字典。 |
keys() | 返回所有鍵的視圖。 |
values() | 返回所有值的視圖。 |
items() | 返回所有 (鍵, 值) 對(duì)的視圖。 |
pop(key, default) | 刪除指定鍵并返回其值,若不存在返回 default(若未提供則 KeyError)。 |
popitem() | 刪除并返回最后一個(gè)插入的鍵值對(duì)(Python 3.7+)。 |
clear() | 清空字典。 |
copy() | 淺拷貝。 |
fromkeys(iterable, value) | 類方法,從可迭代對(duì)象創(chuàng)建字典,所有值初始為 value。 |
10. 字典的性能與底層原理
10.1 哈希表
Python 字典底層使用哈希表(hash table)。每個(gè)鍵通過哈希函數(shù)計(jì)算出一個(gè)整數(shù)索引,用于快速定位存儲(chǔ)位置。因此查找、插入、刪除的平均時(shí)間復(fù)雜度為 O(1),但最壞情況(哈希沖突嚴(yán)重)可能退化為 O(n)。Python 通過開放地址法和偽隨機(jī)探測(cè)解決沖突,并自動(dòng)調(diào)整表的大?。╮ehash)來維持高效。
C/C++ 聯(lián)動(dòng):
- C++
std::unordered_map同樣基于哈希表,平均 O(1),最壞 O(n)。兩者都會(huì)在負(fù)載因子過高時(shí)自動(dòng) rehash。 - C++
std::map基于紅黑樹,時(shí)間復(fù)雜度 O(log n),但內(nèi)存占用相對(duì)穩(wěn)定,且鍵有序。 - Python 字典的哈希函數(shù)對(duì)字符串和整數(shù)做了優(yōu)化,而 C++ 需要為自定義類型特化
std::hash。
10.2 鍵的要求
- 鍵必須是可哈希的:即對(duì)象必須實(shí)現(xiàn)
__hash__()和__eq__()方法,且在其生命周期中哈希值不變。 - 不可變類型(字符串、數(shù)字、元組)通??晒#涣斜?、字典、集合等可變對(duì)象不可哈希。
- 元組中若包含可變對(duì)象,則該元組不可哈希。
# 合法鍵
d = {("a", 1): "tuple"}
# 非法鍵
# d = {["a", 1]: "list"} # TypeError: unhashable type: 'list'代碼解析:
- 元組
("a", 1)中的元素都是不可變類型,因此元組本身可哈希,可以作為鍵。 - 列表
["a", 1]是可變的,不能作為鍵。
C/C++ 聯(lián)動(dòng):C++ 中 unordered_map 的鍵也需要可哈希。內(nèi)置類型已有標(biāo)準(zhǔn)哈希,自定義類型需要提供 hash 特化和 operator==。例如:
struct MyKey {
int a;
std::string b;
bool operator==(const MyKey& other) const { return a==other.a && b==other.b; }
};
namespace std {
template<> struct hash<MyKey> {
size_t operator()(const MyKey& k) const {
return hash<int>()(k.a) ^ (hash<string>()(k.b) << 1);
}
};
}10.3 內(nèi)存占用
字典比列表占用更多內(nèi)存(約 2~3 倍),因?yàn)楣1硇枰A(yù)留額外空間。
11. 擴(kuò)展:collections 模塊中的字典變種
11.1 defaultdict—— 帶默認(rèn)工廠的字典
當(dāng)訪問不存在的鍵時(shí),自動(dòng)創(chuàng)建默認(rèn)值,避免 KeyError
from collections import defaultdict
# 默認(rèn)值為整數(shù) 0
dd = defaultdict(int)
dd["a"] += 1 # 不需要先檢查 "a" 是否存在
print(dd) # {'a': 1}代碼解析:
defaultdict(int)創(chuàng)建了一個(gè)默認(rèn)值為int()(即 0)的字典。當(dāng)訪問不存在的鍵時(shí),自動(dòng)調(diào)用int()生成默認(rèn)值并插入。dd["a"] += 1:由于"a"不存在,defaultdict先設(shè)置dd["a"] = 0,然后執(zhí)行dd["a"] = 0 + 1。
# 默認(rèn)值為空列表
dd2 = defaultdict(list)
dd2["group"].append(10) # 自動(dòng)創(chuàng)建列表
print(dd2) # {'group': [10]}代碼解析:list 工廠函數(shù)會(huì)在鍵缺失時(shí)創(chuàng)建一個(gè)空列表,然后可以安全地 append。
常見工廠:int, list, set, str, 或自定義函數(shù)。
C/C++ 聯(lián)動(dòng):C++ 中 unordered_map 的 operator[] 在鍵不存在時(shí)會(huì)插入默認(rèn)值(值類型的默認(rèn)構(gòu)造)。例如 std::unordered_map<std::string, int> m; m["a"] += 1; 會(huì)先插入 int()(0),再自增。這與 defaultdict(int) 行為類似,但 Python 的 defaultdict 可以靈活指定任何工廠函數(shù)(如 list),而 C++ 的默認(rèn)構(gòu)造只適用于值類型。
11.2 Counter—— 計(jì)數(shù)器
用于統(tǒng)計(jì)可哈希元素出現(xiàn)的次數(shù)。
from collections import Counter
colors = ["red", "blue", "red", "green", "blue", "red"]
cnt = Counter(colors)
print(cnt) # Counter({'red': 3, 'blue': 2, 'green': 1})
print(cnt["red"]) # 3
print(cnt.most_common(2)) # [('red', 3), ('blue', 2)]代碼解析:
Counter(colors)遍歷列表,統(tǒng)計(jì)每個(gè)元素出現(xiàn)的次數(shù),返回一個(gè)類似字典的對(duì)象。cnt["red"]返回'red'出現(xiàn)的次數(shù)。對(duì)于不存在的鍵,返回 0(不報(bào)錯(cuò))。most_common(2)返回出現(xiàn)次數(shù)最多的前 2 個(gè)元素及其次數(shù),按降序排列。
C/C++ 聯(lián)動(dòng):C++ 中沒有 Counter 的直接對(duì)應(yīng),但可以用 unordered_map 實(shí)現(xiàn)計(jì)數(shù),再借助 vector 排序獲取最值。Python 的 Counter 更高級(jí),內(nèi)置了 most_common 等便捷方法。
11.3 OrderedDict—— 保持插入順序(Python 3.7+ 中普通 dict 已有序)
在 Python 3.6 之前,字典無序,OrderedDict 用于保持插入順序?,F(xiàn)在普通 dict 也保持順序,但 OrderedDict 還額外提供了 move_to_end() 等方法。
from collections import OrderedDict
od = OrderedDict()
od["a"] = 1
od["b"] = 2
od.move_to_end("a") # 將 "a" 移到末尾代碼解析:move_to_end(key, last=True) 將指定鍵移動(dòng)到末尾(如果 last=False 則移動(dòng)到開頭)。
C/C++ 聯(lián)動(dòng):C++ 中保持插入順序沒有標(biāo)準(zhǔn)容器直接支持??梢允褂?nbsp;std::vector 配合 unordered_map 來記錄順序,或使用 boost::multi_index。Python 3.7+ 普通 dict 已有序,這是比 C++ 方便的特性。
11.4 ChainMap—— 將多個(gè)字典合并成一個(gè)視圖
用于查找時(shí)按順序搜索多個(gè)字典。
from collections import ChainMap
d1 = {"a": 1, "b": 2}
d2 = {"b": 3, "c": 4}
chain = ChainMap(d1, d2)
print(chain["b"]) # 從 d1 找到 2(取第一個(gè))代碼解析:
ChainMap(d1, d2)創(chuàng)建了一個(gè)虛擬的合并字典,優(yōu)先查找d1,如果d1中沒有再到d2中查找。- 修改
chain會(huì)影響第一個(gè)字典d1。
C/C++ 聯(lián)動(dòng):C++ 無直接對(duì)應(yīng),但可用多個(gè) map 和自定義搜索邏輯實(shí)現(xiàn)。
12. 字典與列表、元組的對(duì)比
| 特性 | 字典 | 列表 | 元組 |
|---|---|---|---|
| 容器類型 | 映射(鍵值對(duì)) | 序列 | 序列 |
| 有序性 | Python 3.7+ 插入有序 | 有序 | 有序 |
| 可變性 | 可變 | 可變 | 不可變 |
| 索引方式 | 鍵(不可變類型) | 整數(shù)索引 | 整數(shù)索引 |
| 查找速度 | 平均 O(1) | O(n) | O(n) |
| 內(nèi)存占用 | 較大 | 中等 | 略小于列表 |
| 典型用途 | 關(guān)聯(lián)數(shù)據(jù)、快速查找 | 有序序列 | 不可變序列 |
13. 字典的應(yīng)用實(shí)戰(zhàn)
13.1 統(tǒng)計(jì)字符串中字符出現(xiàn)次數(shù)
text = "hello world"
freq = {}
for ch in text:
if ch != " ":
freq[ch] = freq.get(ch, 0) + 1
print(freq)代碼解析:
- 遍歷字符串中的每個(gè)字符。
- 跳過空格。
freq.get(ch, 0)獲取字符當(dāng)前的計(jì)數(shù),如果不存在則返回 0,然后加 1 并賦值。- 更優(yōu)雅的方式:使用
Counter(text)。
13.2 使用字典實(shí)現(xiàn)簡(jiǎn)單緩存(記憶化)
def fibonacci(n, cache={}):
if n in cache:
return cache[n]
if n <= 1:
return n
cache[n] = fibonacci(n-1) + fibonacci(n-2)
return cache[n]代碼解析:
- 默認(rèn)參數(shù)
cache={}在函數(shù)定義時(shí)創(chuàng)建一次,后續(xù)調(diào)用會(huì)復(fù)用同一個(gè)字典對(duì)象(注意:可變默認(rèn)參數(shù)要小心使用,但在這里正好用來實(shí)現(xiàn)緩存)。 - 每次計(jì)算
fibonacci(n)時(shí),先檢查緩存,如果已有結(jié)果則直接返回,避免重復(fù)遞歸。
13.3 根據(jù)值排序字典
d = {"apple": 3, "banana": 1, "cherry": 2}
# 按值升序排序,得到鍵的列表
sorted_keys = sorted(d, key=d.get) # ['banana', 'cherry', 'apple']
# 按值降序排序,得到鍵值對(duì)列表
sorted_items = sorted(d.items(), key=lambda x: x[1], reverse=True)代碼解析:
sorted(d, key=d.get):d.get作為鍵函數(shù),對(duì)每個(gè)鍵獲取對(duì)應(yīng)的值,按值排序。結(jié)果返回鍵的列表。sorted(d.items(), key=lambda x: x[1]):d.items()返回(key, value)元組,lambda x: x[1]取元組的第二個(gè)元素(即值)作為排序依據(jù)。
13.4 合并兩個(gè)字典(Python 3.9+ 使用|)
d1 = {"a": 1, "b": 2}
d2 = {"b": 3, "c": 4}
merged = d1 | d2 # {'a':1, 'b':3, 'c':4}
d1 |= d2 # 原地更新(Python 3.9+)代碼解析:
|運(yùn)算符返回一個(gè)新字典,包含兩個(gè)字典的鍵值對(duì),重復(fù)鍵以右邊字典為準(zhǔn)。|=是原地操作,相當(dāng)于d1.update(d2)。
C/C++ 聯(lián)動(dòng):C++ 中合并兩個(gè) unordered_map 無運(yùn)算符重載,需手動(dòng)循環(huán)插入。
14. 常見陷阱與注意事項(xiàng)
| 陷阱 | 說明 | 解決方案 |
|---|---|---|
| 使用可變對(duì)象作為鍵 | 列表、字典等不可哈希,會(huì)報(bào)錯(cuò) | 改用元組或字符串 |
| 在遍歷字典時(shí)修改字典 | 會(huì)導(dǎo)致 RuntimeError: dictionary changed size during iteration | 遍歷 list(d.keys()) 或 d.copy().items() |
混淆 get 和 setdefault | setdefault 會(huì)修改字典,get 不會(huì) | 按需選擇 |
| 認(rèn)為字典總是無序(舊代碼) | Python 3.7+ 插入順序被保證,但依賴此特性的代碼需要最低版本 | 使用 OrderedDict 若需嚴(yán)格兼容低版本 |
在 defaultdict 中傳遞可變對(duì)象 | 工廠函數(shù)使用 list 而非 list(),傳遞可調(diào)用對(duì)象 | defaultdict(list) 正確,defaultdict(list()) 錯(cuò)誤 |
拷貝字典時(shí)使用 = 而非 copy | 二者指向同一對(duì)象,修改會(huì)互相影響 | 淺拷貝用 d.copy(),深拷貝用 copy.deepcopy |
C/C++ 聯(lián)動(dòng):
- C++ 中同樣有遍歷時(shí)刪除導(dǎo)致迭代器失效的問題,通常使用
for (auto it = m.begin(); it != m.end(); ) { if (cond) it = m.erase(it); else ++it; }。 - C++ 的
unordered_map默認(rèn)不保留插入順序,如果需要順序需額外維護(hù)。
以上就是Python字典創(chuàng)建、訪問、修改、刪除及遍歷的完整指南的詳細(xì)內(nèi)容,更多關(guān)于Python字典操作指南的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python實(shí)現(xiàn)PowerPoint演示文稿到圖片的批量轉(zhuǎn)換
PowerPoint演示文稿作為展示創(chuàng)意、分享知識(shí)和表達(dá)觀點(diǎn)的重要工具,被廣泛應(yīng)用于教育、商務(wù)匯報(bào)及個(gè)人項(xiàng)目展示等領(lǐng)域,用Python代碼可以高效地實(shí)現(xiàn)PowerPoint演示文稿到圖片的批量轉(zhuǎn)換,從而提升工作效率,文本將介紹如何使用Python實(shí)現(xiàn)PowerPoint演示文稿到圖片的轉(zhuǎn)換2024-06-06
python代碼如何調(diào)出cmd命令行窗口并在cmd窗口中執(zhí)行指定的命令
這篇文章主要介紹了python代碼如何調(diào)出cmd命令行窗口并在cmd窗口中執(zhí)行指定的命令問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02
python編寫簡(jiǎn)易聊天室實(shí)現(xiàn)局域網(wǎng)內(nèi)聊天功能
這篇文章主要為大家詳細(xì)介紹了python編寫簡(jiǎn)易聊天室實(shí)現(xiàn)局域網(wǎng)內(nèi)聊天功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07
pycharm 多行批量縮進(jìn)和反向縮進(jìn)快捷鍵介紹
這篇文章主要介紹了pycharm 多行批量縮進(jìn)和反向縮進(jìn)快捷鍵介紹,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-01-01
Python3實(shí)現(xiàn)SMTP發(fā)送郵件的實(shí)戰(zhàn)指南
,本文詳細(xì)介紹 Python3 借助smtplib和email庫(kù)實(shí)現(xiàn) SMTP 郵件發(fā)送的方法,從基礎(chǔ)到實(shí)戰(zhàn)覆蓋多場(chǎng)景,先講解 SMTP 協(xié)議定義及兩核心庫(kù)功能,再說明創(chuàng)建 SMTP 對(duì)象和使用sendmail方法的核心語法與參數(shù),需要的朋友可以參考下2025-10-10
淺談Python函數(shù)式編程的返回函數(shù)與匿名函數(shù)
這篇文章主要介紹了淺談Python函數(shù)式編程的返回函數(shù)與匿名函數(shù),如果一個(gè)變量指向了一個(gè)函數(shù),那么,可以通過該變量來調(diào)用這個(gè)函數(shù),需要的朋友可以參考下2023-04-04
Python使用標(biāo)準(zhǔn)庫(kù)turtle實(shí)現(xiàn)浪漫雪花飄落動(dòng)畫效果
這篇文章主要介紹了用 Python 標(biāo)準(zhǔn)庫(kù) turtle 實(shí)現(xiàn)的浪漫雪花飄落動(dòng)畫,595 片六邊形雪花從天而降,配合文字逐幀浮現(xiàn),張萬森、好久不見、下雪了、過的好嗎,氛圍感直接拉滿,需要的朋友可以參考下2026-06-06
Python實(shí)現(xiàn)向服務(wù)器請(qǐng)求壓縮數(shù)據(jù)及解壓縮數(shù)據(jù)的方法示例
這篇文章主要介紹了Python實(shí)現(xiàn)向服務(wù)器請(qǐng)求壓縮數(shù)據(jù)及解壓縮數(shù)據(jù)的方法,涉及Python文件傳輸及zip文件相關(guān)操作技巧,需要的朋友可以參考下2017-06-06

