Python基礎(chǔ)指南之字典遍歷的核心方法詳解
一、開篇:遍歷才是字典操作的靈魂
前面兩篇文章我們學(xué)了字典的創(chuàng)建原理和增刪改查。今天聚焦字典使用中最頻繁的操作——遍歷。
增刪改查是原子操作,而遍歷是批量操作。處理API返回的JSON數(shù)據(jù)、統(tǒng)計用戶行為、構(gòu)建報表——這些任務(wù)都依賴對字典的高效遍歷。Python為字典提供了三種視圖對象:keys()、values() 和 items(),每種都有獨(dú)特的用途和技巧。
但遍歷不僅僅是 for k, v in d.items() 這一種寫法。視圖對象的集合特性、遍歷中的性能考量、嵌套字典的遞歸遍歷、多字典的并行遍歷——這些進(jìn)階技巧能讓你在處理復(fù)雜數(shù)據(jù)時游刃有余。
二、keys()——鍵視圖
2.1 基本遍歷
d = {'name': '小明', 'age': 25, 'city': '北京'}
# 方式一:默認(rèn)迭代——遍歷的是鍵(最簡潔)
for key in d:
print(key)
# name, age, city
# 方式二:顯式調(diào)用keys()
for key in d.keys():
print(key)
# 同上
# 這兩者的效果完全一樣
# 但在Python 2中,d.keys()返回的是列表(復(fù)制),而默認(rèn)迭代返回迭代器
# Python 3中d.keys()返回視圖對象(動態(tài)、不復(fù)制)
# 遍歷時訪問值
for key in d:
print(f'{key} = {d[key]}')
2.2 keys()視圖的集合操作
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# keys()支持集合操作!
keys = d.keys()
# 交集
print(keys & {'a', 'c', 'e'}) # {'a', 'c'}
# 并集
print(keys | {'e', 'f'}) # {'a', 'b', 'c', 'd', 'e', 'f'}
# 差集
print(keys - {'a', 'b'}) # {'c', 'd'}
# 對稱差
print(keys ^ {'a', 'e'}) # {'b', 'c', 'd', 'e'}
# 成員檢查(O(1)?。?
print('a' in d.keys()) # True
print('z' in d.keys()) # False
# 實(shí)用場景:找出兩個字典的公共鍵
d1 = {'name': '小明', 'age': 25, 'city': '北京'}
d2 = {'name': '小紅', 'age': 23, 'job': '設(shè)計師'}
common_keys = d1.keys() & d2.keys()
print(common_keys) # {'name', 'age'}
# 找出只在d1中的鍵
only_in_d1 = d1.keys() - d2.keys()
print(only_in_d1) # {'city'}
# 找出只在一個字典中的鍵(互斥鍵)
exclusive = d1.keys() ^ d2.keys()
print(exclusive) # {'city', 'job'}
2.3 keys()視圖是動態(tài)的
d = {'a': 1, 'b': 2, 'c': 3}
# keys()返回的是視圖——能反映字典的實(shí)時變化
keys_view = d.keys()
print(list(keys_view)) # ['a', 'b', 'c']
# 修改字典后,視圖自動更新
d['d'] = 4
print(list(keys_view)) # ['a', 'b', 'c', 'd']
# 刪除后也更新
del d['a']
print(list(keys_view)) # ['b', 'c', 'd']
# ?? 注意:不能在遍歷視圖時修改字典大小
# for key in d.keys():
# d[f'new_{key}'] = 1 # 可能觸發(fā)RuntimeError
# 如果需要這樣做,先轉(zhuǎn)化為列表
for key in list(d.keys()):
d[f'new_{key}'] = 1
print(d)
# {'b': 2, 'c': 3, 'd': 4, 'new_b': 1, 'new_c': 1, 'new_d': 1}
三、values()——值視圖
3.1 基本遍歷
d = {'name': '小明', 'age': 25, 'city': '北京'}
# 遍歷所有值
for value in d.values():
print(value)
# 小明, 25, 北京
# members檢查(O(n)——因?yàn)橹悼赡懿晃ㄒ唬?
print('小明' in d.values()) # True
print(25 in d.values()) # True
# 值的聚合計算
scores = {'小明': 85, '小紅': 92, '小剛': 78, '小李': 95}
# 求和
total = sum(scores.values())
print(f'總分: {total}') # 350
# 平均值
avg = total / len(scores)
print(f'平均分: {avg:.1f}') # 87.5
# 最大最小值
print(f'最高: {max(scores.values())}') # 95
print(f'最低: {min(scores.values())}') # 78
# 值視圖也是動態(tài)的
values_view = scores.values()
scores['小王'] = 100
print(max(values_view)) # 100(反映了新增的值)
3.2 值視圖的限制
# values()視圖通常不支持集合操作
# 因?yàn)橹悼赡懿晃ㄒ弧⒖赡懿豢晒?
d = {'a': 1, 'b': 2, 'c': 2, 'd': 3}
# print(d.values() & {1, 2}) # 不一定支持(值可能重復(fù))
# 如果需要值的集合操作,先轉(zhuǎn)為set
unique_values = set(d.values())
print(unique_values & {1, 2}) # {1, 2}
# 成員檢查雖然可以用,但需要注意性能
print(2 in d.values()) # True(O(n)檢查)
print(2 in d) # True(但這是在檢查鍵!O(1))
# 重要:in d 檢查的是鍵,不是值!
d = {'name': '小明'}
print('name' in d) # True(鍵存在)
print('小明' in d) # False(這不是鍵,是值?。?
3.3 值視圖的應(yīng)用
# 統(tǒng)計值的分布
scores = {'小明': 85, '小紅': 92, '小剛': 78, '小李': 95, '小王': 85, '小張': 92}
# 統(tǒng)計每個分?jǐn)?shù)出現(xiàn)幾次
from collections import Counter
score_count = Counter(scores.values())
print(score_count) # Counter({85: 2, 92: 2, 78: 1, 95: 1})
# 找出所有重復(fù)的值
duplicated_scores = [score for score, count in score_count.items() if count > 1]
print(f'重復(fù)的分?jǐn)?shù): {duplicated_scores}') # [85, 92]
# 找出得分為85的所有學(xué)生
students_with_85 = [name for name, score in scores.items() if score == 85]
print(f'得85分的學(xué)生: {students_with_85}') # ['小明', '小王']
四、items()——鍵值對視圖
4.1 基本遍歷
d = {'name': '小明', 'age': 25, 'city': '北京'}
# 遍歷鍵值對——最常用的遍歷方式
for key, value in d.items():
print(f'{key} = {value}')
# items()返回的是dict_items視圖對象
items = d.items()
print(items) # dict_items([('name', '小明'), ('age', 25), ('city', '北京')])
print(type(items)) # <class 'dict_items'>
# items()的元素是元組
for pair in d.items():
print(f'{pair[0]}: {pair[1]}') # 可以但不推薦,用解包更好
# 成員檢查(O(1))
print(('name', '小明') in d.items()) # True
print(('name', '小紅') in d.items()) # False(值不匹配)
# items視圖也是動態(tài)的
items_view = d.items()
d['job'] = '工程師'
print(('job', '工程師') in items_view) # True
4.2 items()的集合操作
d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'a': 1, 'b': 20, 'd': 4}
# 找出鍵和值都相同的項
common_items = d1.items() & d2.items()
print(common_items) # {('a', 1)}
# 找出鍵相同但值不同的項
same_keys_diff_values = {
k: (d1[k], d2[k])
for k in d1.keys() & d2.keys()
if d1[k] != d2[k]
}
print(same_keys_diff_values) # {'b': (2, 20)}
# 找出鍵值對差異
added = d2.items() - d1.items() # d2中有而d1中沒有的
removed = d1.items() - d2.items() # d1中有而d2中沒有的
print(f'新增/變化的: {added}') # {('b', 20), ('d', 4)}
print(f'刪除/原值: {removed}') # {('c', 3), ('b', 2)}
4.3 items()的排序和過濾
scores = {'小明': 85, '小紅': 92, '小剛': 78, '小李': 95, '小王': 88}
# 按鍵排序
sorted_by_key = dict(sorted(scores.items()))
print(sorted_by_key) # 按姓名排序
# 按值排序
sorted_by_value = dict(sorted(scores.items(), key=lambda x: x[1]))
print(sorted_by_value) # {'小剛': 78, '小明': 85, '小王': 88, '小紅': 92, '小李': 95}
# 按值降序
sorted_desc = dict(sorted(scores.items(), key=lambda x: x[1], reverse=True))
print(sorted_desc) # {'小李': 95, '小紅': 92, '小王': 88, '小明': 85, '小剛': 78}
# 過濾——找出分?jǐn)?shù)高于85的
high_scores = {k: v for k, v in scores.items() if v > 85}
print(high_scores) # {'小紅': 92, '小李': 95, '小王': 88}
# 取前N名
top3 = dict(sorted(scores.items(), key=lambda x: x[1], reverse=True)[:3])
print(f'前三名: {top3}')
五、遍歷的高級技巧
5.1 遍歷時修改字典
# ?? 黃金法則:不要在遍歷字典時修改它的結(jié)構(gòu)(增減鍵)
# 場景一:需要在遍歷時修改值——可以安全進(jìn)行
prices = {'apple': 10, 'banana': 5, 'orange': 8}
for key in prices:
prices[key] *= 1.1 # 所有價格上漲10%
print(prices) # 安全!只是修改值,沒有改變字典結(jié)構(gòu)
# 場景二:需要在遍歷時增減鍵——先收集再操作
d = {'a': 1, 'b': -2, 'c': 3, 'd': -4, 'e': 5}
# 想刪除所有負(fù)數(shù)值
to_delete = [k for k, v in d.items() if v < 0]
for k in to_delete:
del d[k]
print(d) # {'a': 1, 'c': 3, 'e': 5}
# 場景三:同時增加和刪除——遍歷list(d.keys())的副本
d = {'a': 1, 'b': 2, 'c': 3}
for key in list(d.keys()): # list()創(chuàng)建鍵的靜態(tài)快照
if d[key] >= 2:
d[f'big_{key}'] = d.pop(key)
print(d) # {'a': 1, 'big_b': 2, 'big_c': 3}
5.2 嵌套字典遍歷
# 兩層嵌套字典
school = {
'一年級': {
'一班': 45,
'二班': 42,
'三班': 44,
},
'二年級': {
'一班': 40,
'二班': 43,
},
'三年級': {
'一班': 38,
'二班': 41,
'三班': 39,
},
}
# 遍歷嵌套字典
for grade, classes in school.items():
total = sum(classes.values())
print(f'{grade}: 共{len(classes)}個班, {total}人')
for class_name, count in classes.items():
print(f' {class_name}: {count}人')
# 用遞歸遍歷任意深度的嵌套字典
def traverse_dict(d, path=''):
"""遞歸遍歷嵌套字典——打印所有葉子節(jié)點(diǎn)"""
for key, value in d.items():
current_path = f'{path}.{key}' if path else key
if isinstance(value, dict):
traverse_dict(value, current_path)
else:
print(f'{current_path} = {value}')
config = {
'app': {
'name': 'MyApp',
'version': '2.0',
'database': {
'host': 'localhost',
'port': 5432,
'pool': {
'min': 5,
'max': 20,
},
},
},
}
traverse_dict(config)
# app.name = MyApp
# app.version = 2.0
# app.database.host = localhost
# app.database.port = 5432
# app.database.pool.min = 5
# app.database.pool.max = 20
5.3 多字典并行遍歷
dict1 = {'a': 1, 'b': 2, 'c': 3}
dict2 = {'a': 10, 'b': 20, 'd': 40}
# 并行遍歷兩個字典的所有鍵(并集)
all_keys = dict1.keys() | dict2.keys()
for key in all_keys:
val1 = dict1.get(key, 'N/A')
val2 = dict2.get(key, 'N/A')
print(f'{key}: dict1={val1}, dict2={val2}')
# a: dict1=1, dict2=10
# b: dict1=2, dict2=20
# c: dict1=3, dict2=N/A
# d: dict1=N/A, dict2=40
# 只遍歷公共鍵(交集)
common_keys = dict1.keys() & dict2.keys()
for key in common_keys:
print(f'{key}: {dict1[key]} vs {dict2[key]}')
# 比較兩個字典
def compare_dicts(d1, d2):
"""詳細(xì)比較兩個字典"""
all_keys = d1.keys() | d2.keys()
only_in_d1 = d1.keys() - d2.keys()
only_in_d2 = d2.keys() - d1.keys()
diff_values = {k: (d1[k], d2[k]) for k in d1.keys() & d2.keys()
if d1[k] != d2[k]}
print(f'只在d1: {only_in_d1}')
print(f'只在d2: {only_in_d2}')
print(f'值不同: {diff_values}')
compare_dicts(dict1, dict2)
六、遍歷的性能與實(shí)踐
6.1 遍歷效率對比
import time
d = {f'key_{i}': i for i in range(1000000)}
# 方式一:for key in d(最快——只訪問鍵)
start = time.perf_counter()
for key in d:
_ = key
t1 = time.perf_counter() - start
# 方式二:for key in d.keys()(和方式一幾乎一樣)
start = time.perf_counter()
for key in d.keys():
_ = key
t2 = time.perf_counter() - start
# 方式三:for key, value in d.items()(最常用)
start = time.perf_counter()
for key, value in d.items():
_ = key, value
t3 = time.perf_counter() - start
# 方式四:for key in d + d[key](兩次操作,不推薦)
start = time.perf_counter()
for key in d:
_ = d[key]
t4 = time.perf_counter() - start
print(f'for key in d: {t1:.3f}秒')
print(f'for key in d.keys(): {t2:.3f}秒')
print(f'for k,v in d.items(): {t3:.3f}秒')
print(f'for key in d + d[key]:{t4:.3f}秒')
6.2 最佳實(shí)踐
# 原則一:需要鍵時用 for key in d
for key in d: # 最簡潔
print(key)
# 原則二:需要值但不需要鍵時用 for value in d.values()
total = sum(d.values()) # 甚至不需要顯式循環(huán)
# 原則三:同時需要鍵和值時用 for k, v in d.items()
for key, value in d.items(): # 清晰且高效
print(f'{key} = {value}')
# 原則四:要修改字典值時可以直接遍歷鍵
for key in d:
d[key] = transform(d[key]) # 安全:只改值,不改結(jié)構(gòu)
# 原則五:要修改字典結(jié)構(gòu)時遍歷list(d.keys())
for key in list(d.keys()):
if should_delete(d[key]):
del d[key]
# 原則六:創(chuàng)建新字典比在遍歷中修改更安全
filtered = {k: v for k, v in d.items() if condition(v)}
七、實(shí)戰(zhàn):數(shù)據(jù)處理流水線
def analyze_survey(responses):
"""
分析問卷調(diào)查結(jié)果
輸入:[{'name': 'xx', 'age': 25, 'score': 85, 'city': 'Beijing'}, ...]
"""
# 遍歷統(tǒng)計
city_counts = {}
age_groups = {'青年(<=30)': 0, '中年(31-50)': 0, '老年(>50)': 0}
total_score = 0
scores_list = []
for r in responses:
# 城市統(tǒng)計
city = r.get('city', '未知')
city_counts[city] = city_counts.get(city, 0) + 1
# 年齡分組
age = r.get('age', 0)
if age <= 30:
age_groups['青年(<=30)'] += 1
elif age <= 50:
age_groups['中年(31-50)'] += 1
else:
age_groups['老年(>50)'] += 1
# 分?jǐn)?shù)統(tǒng)計
score = r.get('score', 0)
total_score += score
scores_list.append(score)
avg_score = total_score / len(responses) if responses else 0
scores_list.sort()
return {
'total': len(responses),
'city_distribution': city_counts,
'age_distribution': age_groups,
'avg_score': round(avg_score, 1),
'median_score': scores_list[len(scores_list) // 2] if scores_list else 0,
'highest_score': scores_list[-1] if scores_list else 0,
'lowest_score': scores_list[0] if scores_list else 0,
}
# 模擬數(shù)據(jù)
survey_data = [
{'name': '小明', 'age': 25, 'score': 85, 'city': '北京'},
{'name': '小紅', 'age': 32, 'score': 92, 'city': '上海'},
{'name': '小剛', 'age': 28, 'score': 78, 'city': '北京'},
{'name': '小李', 'age': 45, 'score': 95, 'city': '廣州'},
{'name': '小王', 'age': 55, 'score': 88, 'city': '上海'},
]
result = analyze_survey(survey_data)
for key, value in result.items():
print(f'{key}: {value}')
八、本篇小結(jié)
字典的三種視圖對象各有其最佳場景:
d.keys():鍵視圖,支持集合操作(交集、并集、差集),成員檢查O(1)d.values():值視圖,適合聚合運(yùn)算(sum/max/min),成員檢查O(n)d.items():鍵值對視圖,最常用的遍歷方式,支持解包和集合操作
關(guān)鍵規(guī)則:
- 只遍歷鍵 →
for k in d(不需要顯式調(diào)用keys()) - 只遍歷值 →
for v in d.values() - 同時遍歷鍵和值 →
for k, v in d.items() - 不要在遍歷時修改字典結(jié)構(gòu) → 先收集再操作,或遍歷
list(d.keys()) - 視圖是動態(tài)的 → 會反映字典的實(shí)時變化
字典遍歷是Python日常編程的基礎(chǔ)功。下一篇我們學(xué)習(xí)字典推導(dǎo)式與字典合并技巧,進(jìn)一步提升字典操作的效率。
到此這篇關(guān)于Python基礎(chǔ)指南之字典遍歷的核心方法詳解的文章就介紹到這了,更多相關(guān)Python字典遍歷內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python中halcon環(huán)境配置的詳細(xì)步驟
這篇文章主要為大家詳細(xì)介紹了python中halcon環(huán)境配置的詳細(xì)步驟,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,有需要的小伙伴可以了解一下2025-06-06
Numpy中np.vstack()?和?np.hstack()?的實(shí)現(xiàn)
本文主要介紹了Numpy中np.vstack()和np.hstack()的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-04-04
Python常見100個經(jīng)典面試問題總結(jié)(從入門到進(jìn)階)
Python是一種高級、解釋型、通用的編程語言,以其簡潔易讀的語法而聞名,適用于廣泛的應(yīng)用,包括Web開發(fā)、數(shù)據(jù)分析、人工智能和自動化腳本,這篇文章主要介紹了Python常見100個經(jīng)典面試問題總結(jié)的相關(guān)資料,需要的朋友可以參考下2026-06-06
Python獲取excel內(nèi)容及相關(guān)操作代碼實(shí)例
這篇文章主要介紹了Python獲取excel內(nèi)容及相關(guān)操作代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-08-08

