Python基礎(chǔ)指南之字典增刪改查操作全攻略
一、開(kāi)篇:字典操作,CRUD是核心
上一篇文章我們學(xué)習(xí)了字典的創(chuàng)建方式和底層原理。今天我們要掌握使用字典最日常的操作——增刪改查(CRUD)。
無(wú)論你是在處理用戶數(shù)據(jù)、構(gòu)建緩存、解析JSON配置還是做數(shù)據(jù)轉(zhuǎn)換,字典的增刪改查都是你每天最頻繁的操作。和列表不同,字典的操作圍繞鍵展開(kāi)——增是通過(guò)鍵賦值,刪是按鍵刪除,改是按鍵更新,查是按鍵獲取。
這篇文章會(huì)從最基本的鍵值操作講起,深入到各種高級(jí)模式:setdefault()的妙用、字典合并的多種姿勢(shì)、pop()和del的區(qū)別、update()的靈活傳參,以及各種"看起來(lái)能行但不行的"操作和它們的正確替代方式。
二、增——把新數(shù)據(jù)放進(jìn)字典
2.1 直接賦值(最常用)
# 最基本的增加:dict[key] = value
person = {}
person['name'] = '小明'
person['age'] = 25
person['city'] = '北京'
print(person) # {'name': '小明', 'age': 25, 'city': '北京'}
# 如果鍵已存在,則是更新(不會(huì)報(bào)錯(cuò))
person['age'] = 26
print(person) # {'name': '小明', 'age': 26, 'city': '北京'}
# 鍵可以是任何不可變類(lèi)型
d = {}
d[(1, 2)] = 'point A'
d[42] = 'answer'
print(d) # {(1, 2): 'point A', 42: 'answer'}
2.2 update()——批量添加
person = {'name': '小明'}
# 方式一:用字典update
person.update({'age': 25, 'city': '北京'})
print(person) # {'name': '小明', 'age': 25, 'city': '北京'}
# 方式二:用關(guān)鍵字參數(shù)(鍵必須是合法標(biāo)識(shí)符)
person.update(age=26, job='工程師')
print(person) # {'name': '小明', 'age': 26, 'city': '北京', 'job': '工程師'}
# 方式三:用可迭代對(duì)象(每個(gè)元素為(key, value)對(duì))
person.update([('hobby', '編程'), ('level', 5)])
print(person)
# {'name': '小明', 'age': 26, 'city': '北京', 'job': '工程師', 'hobby': '編程', 'level': 5}
# 方式四:混合
person.update({'company': 'Tech公司'}, department='研發(fā)部')
print(person['company'], person['department']) # Tech公司 研發(fā)部
# update()會(huì)覆蓋已存在的鍵
person.update({'name': '小紅'})
print(person['name']) # 小紅(被覆蓋了)
2.3 setdefault()——不存在才設(shè)置
# setdefault(key, default):
# - 如果key存在:返回已有的值(不修改)
# - 如果key不存在:設(shè)置key=default,返回default
# 基本用法
person = {'name': '小明', 'age': 25}
# 'name'存在,返回已有值
name = person.setdefault('name', '未知')
print(name) # 小明(沒(méi)有被修改)
# 'city'不存在,設(shè)置默認(rèn)值
city = person.setdefault('city', '北京')
print(city) # 北京
print(person) # {'name': '小明', 'age': 25, 'city': '北京'}
# setdefault的經(jīng)典用法:分組歸類(lèi)
words = ['apple', 'banana', 'apricot', 'cherry', 'blueberry', 'coconut']
by_first = {}
for word in words:
first = word[0]
# 如果first不存在,創(chuàng)建一個(gè)空列表;如果存在,返回已有的列表
by_first.setdefault(first, []).append(word)
print(by_first)
# {'a': ['apple', 'apricot'], 'b': ['banana', 'blueberry'], 'c': ['cherry', 'coconut']}
# 另一個(gè)經(jīng)典用法:計(jì)數(shù)
text = 'hello world hello python world hello'
word_count = {}
for word in text.split():
word_count[word] = word_count.setdefault(word, 0) + 1
print(word_count) # {'hello': 3, 'world': 2, 'python': 1}
# 或更簡(jiǎn)單的版本(用get)
word_count = {}
for word in text.split():
word_count[word] = word_count.get(word, 0) + 1
setdefault() 和 get() 的區(qū)別:get() 只返回默認(rèn)值但不修改字典,setdefault() 返回默認(rèn)值的同時(shí)會(huì)把默認(rèn)值寫(xiě)入字典。
2.4 字典合并(Python 3.5+)
# 方式一:| 運(yùn)算符(Python 3.9+,最推薦)
d1 = {'a': 1, 'b': 2}
d2 = {'c': 3, 'd': 4}
merged = d1 | d2
print(merged) # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# 有重復(fù)鍵時(shí),右邊的覆蓋左邊的
d3 = {'a': 100, 'e': 5}
merged2 = d1 | d3
print(merged2) # {'a': 100, 'b': 2, 'e': 5}(d3的'a'覆蓋了d1的'a')
# 方式二:**解包合并(Python 3.5+)
merged3 = {**d1, **d2, **d3}
print(merged3) # {'a': 100, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
# 方式三:|= 原地合并(Python 3.9+)
d1 = {'a': 1, 'b': 2}
d1 |= {'c': 3, 'a': 100}
print(d1) # {'a': 100, 'b': 2, 'c': 3}
# 方式四:update()(Python 3.0+)
d1.update(d2, d3) # 原地修改
# 注意區(qū)別:
# | 和 ** 返回新字典
# |= 和 update() 原地修改現(xiàn)有字典
三、刪——從字典中移除數(shù)據(jù)
3.1 pop()——彈出并返回值
person = {'name': '小明', 'age': 25, 'city': '北京', 'job': '工程師'}
# pop(key):刪除鍵并返回對(duì)應(yīng)的值
job = person.pop('job')
print(job) # 工程師
print(person) # {'name': '小明', 'age': 25, 'city': '北京'}
# pop(key, default):鍵不存在時(shí)返回默認(rèn)值(不報(bào)錯(cuò))
hobby = person.pop('hobby', '未知')
print(hobby) # 未知
print(person) # 不變
# 不帶默認(rèn)值的pop在鍵不存在時(shí)拋出KeyError
# person.pop('hobby') # KeyError: 'hobby'
3.2 popitem()——彈出一個(gè)鍵值對(duì)
person = {'name': '小明', 'age': 25, 'city': '北京'}
# Python 3.7+ popitem()彈出最后插入的鍵值對(duì)(LIFO)
last = person.popitem()
print(last) # ('city', '北京')
print(person) # {'name': '小明', 'age': 25}
# 繼續(xù)彈出
print(person.popitem()) # ('age', 25)
print(person.popitem()) # ('name', '小明')
# 空字典popitem()拋出KeyError
# {}.popitem() # KeyError: 'popitem(): dictionary is empty'
# popitem()在清理緩存時(shí)很有用(逐個(gè)處理并移除)
cache = {'key1': 'val1', 'key2': 'val2', 'key3': 'val3'}
while cache:
key, value = cache.popitem()
print(f'處理緩存: {key} = {value}')
3.3 del 語(yǔ)句——按鍵刪除
person = {'name': '小明', 'age': 25, 'city': '北京'}
# del d[key]:刪除指定鍵
del person['city']
print(person) # {'name': '小明', 'age': 25}
# 鍵不存在時(shí)拋出KeyError
# del person['job'] # KeyError: 'job'
# 安全刪除
key_to_delete = 'hobby'
if key_to_delete in person:
del person[key_to_delete]
# 或者用pop
person.pop('hobby', None)
# del可以刪除整個(gè)字典
del person
# print(person) # NameError: name 'person' is not defined
3.4 clear()——清空整個(gè)字典
person = {'name': '小明', 'age': 25, 'city': '北京'}
# clear()清空字典
person.clear()
print(person) # {}
# ?? 注意:clear() vs 重新賦值為{}
config = {'host': 'localhost', 'port': 8080}
ref = config # ref指向同一個(gè)字典
config = {} # config指向新字典
print(ref) # {'host': 'localhost', 'port': 8080}(ref不受影響)
config = {'host': 'localhost', 'port': 8080}
ref = config
config.clear() # 清空原字典
print(ref) # {}(ref也看到字典被清空了)
3.5 條件刪除——按條件過(guò)濾
# 刪除值小于90的鍵值對(duì)
scores = {'小明': 85, '小紅': 92, '小剛': 78, '小李': 95, '小王': 88}
# 方式一:字典推導(dǎo)式(創(chuàng)建新字典,推薦)
high_scores = {k: v for k, v in scores.items() if v >= 90}
print(high_scores) # {'小紅': 92, '小李': 95}
# 方式二:原地修改(收集后再刪)
scores = {'小明': 85, '小紅': 92, '小剛': 78, '小李': 95, '小王': 88}
to_delete = [k for k, v in scores.items() if v < 90]
for k in to_delete:
del scores[k]
print(scores) # {'小紅': 92, '小李': 95}
# 刪除值類(lèi)型不滿足條件的
mixed = {'a': 1, 'b': 'hello', 'c': 2, 'd': 'world'}
numbers_only = {k: v for k, v in mixed.items() if isinstance(v, int)}
print(numbers_only) # {'a': 1, 'c': 2}
四、改——更新已有的值
4.1 直接賦值改
person = {'name': '小明', 'age': 25, 'city': '北京'}
# 修改單個(gè)值
person['age'] = 26
print(person) # {'name': '小明', 'age': 26, 'city': '北京'}
# 修改不存在的鍵——不是修改,是新增!
person['job'] = '工程師'
print(person) # {'name': '小明', 'age': 26, 'city': '北京', 'job': '工程師'}
# Python沒(méi)有"修改不存在的鍵就報(bào)錯(cuò)"的語(yǔ)法
# 如果需要這種語(yǔ)義,必須先檢查
# if 'key' in d: d['key'] = new_value
4.2 update()——批量修改
person = {'name': '小明', 'age': 25, 'city': '北京'}
# 批量更新
person.update({'age': 26, 'city': '上海', 'job': '工程師'})
print(person)
# {'name': '小明', 'age': 26, 'city': '上海', 'job': '工程師'}
# age和city被更新了,job被新增了
# update也接受關(guān)鍵字參數(shù)
person.update(name='小紅', hobby='編程')
print(person)
# {'name': '小紅', 'age': 26, 'city': '上海', 'job': '工程師', 'hobby': '編程'}
4.3 按條件修改
# 對(duì)字典的值做批量變換
prices = {'apple': 10, 'banana': 5, 'orange': 8}
# 所有商品打8折
prices = {k: v * 0.8 for k, v in prices.items()}
print(prices) # {'apple': 8.0, 'banana': 4.0, 'orange': 6.4}
# 只對(duì)價(jià)格高于7的打8折
prices = {'apple': 10, 'banana': 5, 'orange': 8}
prices = {k: v * 0.8 if v > 7 else v for k, v in prices.items()}
print(prices) # {'apple': 8.0, 'banana': 5, 'orange': 6.4}
# 對(duì)鍵做變換
original = {'user_name': 'xiaoming', 'user_age': '25', 'user_city': 'beijing'}
# 去掉"user_"前綴
cleaned = {k.replace('user_', ''): v for k, v in original.items()}
print(cleaned) # {'name': 'xiaoming', 'age': '25', 'city': 'beijing'}
4.4 將修改表達(dá)式直接用于值
# 在現(xiàn)有值的基礎(chǔ)上修改
counts = {'a': 1, 'b': 2, 'c': 3}
# 方式一:用get
counts['a'] = counts.get('a', 0) + 1
# 方式二:用collections.Counter
from collections import Counter
counter = Counter(counts)
counter['a'] += 1
counter['d'] += 1 # 不存在的鍵自動(dòng)從0開(kāi)始計(jì)數(shù)
print(counter) # Counter({'a': 2, 'b': 2, 'c': 3, 'd': 1})
# 方式三:用defaultdict
from collections import defaultdict
# 對(duì)值做列表追加
groups = defaultdict(list)
groups['fruit'].append('apple')
groups['fruit'].append('banana')
groups['vegetable'].append('carrot')
print(dict(groups))
# {'fruit': ['apple', 'banana'], 'vegetable': ['carrot']}
# 對(duì)值做整數(shù)遞增
scores = defaultdict(int)
scores['小明'] += 10
scores['小紅'] += 20
scores['小明'] += 5
print(dict(scores))
# {'小明': 15, '小紅': 20}
五、查——從字典中獲取數(shù)據(jù)
5.1 d[key]——直接訪問(wèn)
person = {'name': '小明', 'age': 25, 'city': '北京'}
# 直接訪問(wèn)——鍵不存在時(shí)拋KeyError
print(person['name']) # 小明
# print(person['job']) # KeyError: 'job'
# 適用場(chǎng)景:確定鍵一定存在時(shí)(如解析已知格式的數(shù)據(jù))
5.2 get()——安全的獲取
person = {'name': '小明', 'age': 25}
# get(key, default):鍵不存在時(shí)返回默認(rèn)值
print(person.get('name', '未知')) # 小明
print(person.get('job', '未知')) # 未知
print(person.get('city')) # None(不指定default時(shí)默認(rèn)是None)
# get的經(jīng)典用法:計(jì)數(shù)
text = 'hello world hello python world hello'
word_count = {}
for word in text.split():
word_count[word] = word_count.get(word, 0) + 1
print(word_count) # {'hello': 3, 'world': 2, 'python': 1}
# get的嵌套使用——安全訪問(wèn)嵌套字典
config = {
'database': {
'host': 'localhost',
'port': 5432,
}
}
# 不安全的嵌套訪問(wèn)
# port = config['cache']['port'] # KeyError: 'cache'
# 安全的嵌套訪問(wèn)(用get鏈)
port = config.get('cache', {}).get('port', 6379)
print(port) # 6379(返回默認(rèn)值)
5.3 in 操作符——檢查鍵是否存在
person = {'name': '小明', 'age': 25}
# 檢查鍵是否存在
print('name' in person) # True
print('job' in person) # False
print('name' not in person) # False
# 檢查值是否存在(注意:這是O(n)的?。?
print('小明' in person.values()) # True
print(25 in person.values()) # True
# 使用場(chǎng)景
if 'error' in response:
print(f'錯(cuò)誤: {response["error"]}')
# 和get()的對(duì)比
# in + []:兩次查找(先檢查,再獲?。?
if 'name' in person:
name = person['name']
# get():一次查找(更高效)
name = person.get('name', '默認(rèn)值')
5.4 遍歷查找
scores = {'小明': 85, '小紅': 92, '小剛': 78, '小李': 95}
# 遍歷全部
for name in scores:
print(f'{name}: {scores[name]}分')
# 遍歷鍵值對(duì)(推薦)
for name, score in scores.items():
print(f'{name}: {score}分')
# 查找最高分的人
top_student = max(scores, key=scores.get)
print(f'最高分: {top_student} ({scores[top_student]}分)')
# 查找所有及格的人
passing = {name for name, score in scores.items() if score >= 60}
print(f'及格: {passing}')
# 查找特定值的鍵(反向查找——注意值可能重復(fù))
def find_keys(d, value):
"""找出所有值為value的鍵"""
return [k for k, v in d.items() if v == value]
d = {'a': 1, 'b': 2, 'c': 1, 'd': 3, 'e': 1}
print(find_keys(d, 1)) # ['a', 'c', 'e']
六、實(shí)戰(zhàn)綜合——用戶管理
class UserManager:
"""用字典管理用戶數(shù)據(jù)——綜合CRUD操作"""
def __init__(self):
self._users = {} # {user_id: user_data}
def create(self, user_id, name, email, role='user'):
"""增加用戶"""
if user_id in self._users:
raise ValueError(f'用戶 {user_id} 已存在')
self._users[user_id] = {
'name': name,
'email': email,
'role': role,
'active': True,
'created_at': '2025-06-01',
}
return self._users[user_id]
def read(self, user_id):
"""查詢用戶"""
user = self._users.get(user_id)
if not user:
return None
return user.copy() # 返回副本,保護(hù)內(nèi)部數(shù)據(jù)
def update(self, user_id, **kwargs):
"""更新用戶——支持關(guān)鍵字參數(shù)"""
if user_id not in self._users:
raise KeyError(f'用戶 {user_id} 不存在')
self._users[user_id].update(kwargs)
return self._users[user_id]
def delete(self, user_id):
"""刪除用戶"""
return self._users.pop(user_id, None)
def list_all(self, role=None, active_only=True):
"""列出用戶——支持過(guò)濾"""
result = {}
for uid, data in self._users.items():
if active_only and not data['active']:
continue
if role and data['role'] != role:
continue
result[uid] = data.copy()
return result
def deactivate(self, user_id):
"""停用用戶(軟刪除)"""
if user_id in self._users:
self._users[user_id]['active'] = False
return True
return False
def count(self):
return len(self._users)
# 使用示例
manager = UserManager()
manager.create(1, '小明', 'xm@test.com', 'admin')
manager.create(2, '小紅', 'xh@test.com')
manager.create(3, '小剛', 'xg@test.com', 'editor')
# 查詢
print(manager.read(1))
# 更新
manager.update(2, role='moderator', email='xh_new@test.com')
# 刪除
manager.delete(3)
# 列出所有
print(f'總共有 {manager.count()} 個(gè)用戶')
for uid, data in manager.list_all().items():
print(f' [{uid}] {data["name"]} ({data["role"]})')
七、常見(jiàn)錯(cuò)誤和陷阱
7.1 運(yùn)行中修改字典大小
# ?? 經(jīng)典錯(cuò)誤:在遍歷字典時(shí)修改它
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# 錯(cuò)誤寫(xiě)法——會(huì)拋出RuntimeError
# for key in d:
# if d[key] % 2 == 0:
# del d[key] # RuntimeError: dictionary changed size during iteration
# 正確方式一:先收集,再刪除
to_delete = [k for k, v in d.items() if v % 2 == 0]
for k in to_delete:
del d[k]
print(d) # {'a': 1, 'c': 3}
# 正確方式二:字典推導(dǎo)式(創(chuàng)建新字典)
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
d = {k: v for k, v in d.items() if v % 2 != 0}
print(d) # {'a': 1, 'c': 3}
# 正確方式三:在list(d.keys())上遍歷
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
for key in list(d.keys()):
if d[key] % 2 == 0:
del d[key]
print(d) # {'a': 1, 'c': 3}
7.2 可變對(duì)象作為默認(rèn)值的陷阱
# ?? fromkeys的陷阱
# keys = ['a', 'b', 'c']
# d = dict.fromkeys(keys, []) # 所有的鍵共享同一個(gè)列表!
# d['a'].append(1)
# print(d) # {'a': [1], 'b': [1], 'c': [1]} ← 全都變了!
# 正確方式:用推導(dǎo)式
d = {k: [] for k in ['a', 'b', 'c']}
d['a'].append(1)
print(d) # {'a': [1], 'b': [], 'c': []}
7.3 非可哈希的鍵
# ?? 不能用列表或字典作為鍵
# d = {}
# d[[1, 2]] = 'value' # TypeError: unhashable type: 'list'
# d[{'a': 1}] = 'value' # TypeError: unhashable type: 'dict'
# 如果確實(shí)需要,用元組代替列表
d = {}
d[(1, 2)] = 'value' # 正確
# 用frozenset代替集合
d = {}
d[frozenset([1, 2])] = 'value' # 正確
八、本篇小結(jié)
字典CRUD操作核心速查:
增(Create):
d[key] = value—— 直接賦值d.update({...})—— 批量添加d.setdefault(key, default)—— 不存在才設(shè)置d1 | d2(Python 3.9+)—— 合并創(chuàng)建新字典
刪(Delete):
d.pop(key)—— 彈出值,鍵不存在拋KeyErrord.pop(key, default)—— 彈出值,鍵不存在返回默認(rèn)值d.popitem()—— 彈出最后一個(gè)鍵值對(duì)(LIFO)del d[key]—— 按鍵刪除d.clear()—— 清空整個(gè)字典
改(Update):
d[key] = new_value—— 直接賦值d.update({...})—— 批量更新- 字典推導(dǎo)式
{k: transform(v) for k, v in d.items()}—— 批量變換
查(Read):
d[key]—— 直接訪問(wèn)(鍵不存在拋KeyError)d.get(key, default)—— 安全獲取key in d—— 檢查鍵是否存在d.keys()/d.values()/d.items()—— 遍歷
字典的增刪改查看似簡(jiǎn)單,但 setdefault()、get()、update() 等方法的嫻熟運(yùn)用,能讓你的字典操作代碼大幅簡(jiǎn)化。下一篇我們將詳細(xì)學(xué)習(xí)字典的keys、values與items遍歷的各種技巧。
到此這篇關(guān)于Python基礎(chǔ)指南之字典增刪改查操作全攻略的文章就介紹到這了,更多相關(guān)Python字典增刪改查操作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python 使用事件對(duì)象asyncio.Event來(lái)同步協(xié)程的操作
這篇文章主要介紹了python 使用事件對(duì)象asyncio.Event來(lái)同步協(xié)程的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05
python密碼學(xué)換位密碼及換位解密轉(zhuǎn)置加密教程
這篇文章主要為大家介紹了python密碼學(xué)換位密碼及換位解密轉(zhuǎn)置加密教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
Python進(jìn)程和線程之多線程的使用及說(shuō)明
Python多線程通過(guò)threading模塊實(shí)現(xiàn),主線程默認(rèn)運(yùn)行,子線程由Thread類(lèi)創(chuàng)建并啟動(dòng),線程共享變量易引發(fā)數(shù)據(jù)混亂,需用Lock同步,但鎖可能降低效率或?qū)е滤梨i,(79字)2025-09-09
使用Python的開(kāi)發(fā)框架Brownie部署以太坊智能合約
在本文中,我們將使用Python部署智能合約。這篇文章可能是您走向智能合約和區(qū)塊鏈開(kāi)發(fā)的橋梁!2021-05-05
python使用for...else跳出雙層嵌套循環(huán)的方法實(shí)例
這篇文章主要給大家介紹了關(guān)于python使用for...else跳出雙層嵌套循環(huán)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用python具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
Python實(shí)現(xiàn)調(diào)整Excel的內(nèi)容高度
本文介紹了一種自動(dòng)調(diào)整Excel行高的Python實(shí)現(xiàn)方法,代碼實(shí)現(xiàn)了自動(dòng)計(jì)算行高、批量處理多個(gè)Excel文件的功能并提供了進(jìn)度提示,希望對(duì)大家有所幫助2026-05-05
Python數(shù)據(jù)結(jié)構(gòu)與算法之圖的基本實(shí)現(xiàn)及迭代器實(shí)例詳解
這篇文章主要介紹了Python數(shù)據(jù)結(jié)構(gòu)與算法之圖的基本實(shí)現(xiàn)及迭代器,結(jié)合實(shí)例形式詳細(xì)分析了數(shù)據(jù)結(jié)構(gòu)與算法中圖的實(shí)現(xiàn)及迭代器相關(guān)算法原理與操作技巧,需要的朋友可以參考下2017-12-12
Python使用Matplotlib繪制甘特圖的實(shí)踐
甘特圖已經(jīng)發(fā)展成項(xiàng)目規(guī)劃和跟蹤的必備工具,本文主要介紹了Python使用Matplotlib繪制甘特圖的實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12

