Python字典:键值对、get()方法、defaultdict,附通讯录实战
上一篇文章讲了列表,列表是按顺序存放数据的。但有时候我们不需要顺序,而是需要"按名字找电话"这种"键值对应"的关系------这时候就要用字典了。
一句话概括
这篇文章解决一个问题:学会Python字典的键值对操作,理解get()方法和defaultdict的用法。
什么是字典
字典用花括号 {} 表示,里面存的是键值对(key-value pairs):
python
# 键是字符串,值是数字
ages = {"小明": 18, "小红": 20, "小李": 22}
# 键是字符串,值是字符串
person = {"name": "张三", "city": "北京", "job": "工程师"}
# 键可以是多种类型
mixed = {1: "one", "two": 2, False: "false"}
# 列表不能作为键(不可哈希)
# 错误:{[1,2]: "value"} # TypeError
# 正确:(1,2)可以作为键
创建字典
python
# 直接创建
person = {"name": "张三", "age": 18, "city": "北京"}
# 用 dict() 函数
person = dict(name="张三", age=18, city="北京")
# 用 zip() 合并两个列表
keys = ["name", "age", "city"]
values = ["张三", 18, "北京"]
person = dict(zip(keys, values)) # {'name': '张三', 'age': 18, 'city': '北京'}
# 空字典
empty = {}
查:访问字典
通过键访问值
python
person = {"name": "张三", "age": 18, "city": "北京"}
print(person["name"]) # 张三
print(person["age"]) # 18
注意 :如果键不存在,会报 KeyError!
python
print(person["job"]) # KeyError: 'job'
安全访问:用 get()
python
person = {"name": "张三", "age": 18}
print(person.get("name")) # 张三
print(person.get("job")) # None(不报错,返回None)
print(person.get("job", "未知")) # 未知(键不存在时返回默认值)
建议 :所有字典访问优先用 get(),避免 KeyError。
改:添加和修改
python
person = {"name": "张三", "age": 18}
# 添加新键值对
person["city"] = "北京" # {'name': '张三', 'age': 18, 'city': '北京'}
# 修改已存在的值
person["age"] = 19 # {'name': '张三', 'age': 19, 'city': '北京'}
删:删除键值对
python
person = {"name": "张三", "age": 18, "city": "北京"}
# pop():删除指定键,返回值
age = person.pop("age") # 删除'age'键,返回18,person={'name': '张三', 'city': '北京'}
# del:删除指定键(不返回值)
del person["city"] # person={'name': '张三'}
# popitem():删除最后一个键值对
person = {"name": "张三", "age": 18, "city": "北京"}
key, value = person.popitem() # ('city', '北京'),person={'name': '张三', 'age': 18}
# clear():清空字典
person.clear() # {}
遍历字典
python
person = {"name": "张三", "age": 18, "city": "北京"}
# 遍历键
for key in person:
print(key)
# 输出:name, age, city
# 遍历值
for value in person.values():
print(value)
# 输出:张三, 18, 北京
# 遍历键值对
for key, value in person.items():
print(f"{key}: {value}")
# 输出:name: 张三, age: 18, city: 北京
# 字典推导式
squares = {x: x**2 for x in range(5)} # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
defaultdict:默认值字典
这是字典的一个进阶用法,来自 collections 模块。
普通字典的问题
python
# 普通字典
word_count = {}
# 统计单词出现次数
words = ["apple", "banana", "apple", "cherry", "banana", "apple"]
for word in words:
if word in word_count:
word_count[word] += 1
else:
word_count[word] = 1
print(word_count) # {'apple': 3, 'banana': 2, 'cherry': 1}
每次都要判断键是否存在,很麻烦。
用 defaultdict 简化
python
from collections import defaultdict
word_count = defaultdict(int) # 默认值是0
words = ["apple", "banana", "apple", "cherry", "banana", "apple"]
for word in words:
word_count[word] += 1 # 如果键不存在,会自动初始化为0
print(dict(word_count)) # {'apple': 3, 'banana': 2, 'cherry': 1}
defaultdict(int) 的意思是:如果键不存在,自动创建并赋值为 int() 的默认值(即0)。
defaultdict 的其他默认值类型
python
from collections import defaultdict
# 默认值是0
dd_int = defaultdict(int)
# 默认值是空列表
dd_list = defaultdict(list)
dd_list["fruits"].append("apple") # {'fruits': ['apple']}
# 默认值是空字典
dd_dict = defaultdict(dict)
# 默认值是集合
dd_set = defaultdict(set)
dd_set["colors"].add("red") # {'colors': {'red'}}
实战练习:词频统计
用字典做一个中英文词频统计工具:
python
from collections import defaultdict
import re
def count_words(text):
"""统计文本中单词出现次数"""
# 提取单词(只保留字母,忽略标点符号和数字)
words = re.findall(r'[a-zA-Z]+', text.lower())
# 用 defaultdict 统计
word_count = defaultdict(int)
for word in words:
word_count[word] += 1
return word_count
def show_top_words(word_count, n=10):
"""显示前n个最高频的词"""
# 按出现次数排序
sorted_words = sorted(word_count.items(), key=lambda x: x[1], reverse=True)
print(f"\n{'排名':<6}{'单词':<15}{'出现次数':<10}")
print("-" * 30)
for i, (word, count) in enumerate(sorted_words[:n], 1):
print(f"{i:<6}{word:<15}{count:<10}")
# 测试
text = """
Python is a great programming language. Python is used for web development,
data science, artificial intelligence, and many more. Python has a simple
syntax that makes it easy to learn and read. Many people love Python.
"""
result = count_words(text)
show_top_words(result)
实战练习:多层嵌套字典
用字典模拟一个班级管理系统:
python
# 班级数据:多层嵌套字典
classroom = {
"class_a": {
"teacher": "李老师",
"students": {
"001": {"name": "小明", "math": 95, "english": 88},
"002": {"name": "小红", "math": 87, "english": 92},
"003": {"name": "小李", "math": 78, "english": 85},
}
},
"class_b": {
"teacher": "王老师",
"students": {
"001": {"name": "小刚", "math": 91, "english": 79},
"002": {"name": "小芳", "math": 85, "english": 90},
}
}
}
# 查询:class_a的小红数学成绩
math_score = classroom["class_a"]["students"]["002"]["math"]
print(f"小红的数学成绩:{math_score}") # 87
# 统计:所有学生的平均数学成绩
all_math_scores = []
for cls in classroom.values():
for student in cls["students"].values():
all_math_scores.append(student["math"])
avg_math = sum(all_math_scores) / len(all_math_scores)
print(f"班级平均数学成绩:{avg_math:.1f}") # 87.2
常见问题FAQ
Q1:字典的键有什么限制?
字典的键必须是**可哈希(hashable)**的对象:
- 可以:字符串、数字、元组、布尔值
- 不可以:列表、字典、集合
python
# 合法
d = {(1, 2): "tuple key"}
d = {"string": "value"}
d = {1: "int key"}
# 非法
d = {[1, 2]: "list key"} # 报错!列表不可哈希
Q2:字典和列表怎么选?
| 场景 | 用什么 |
|---|---|
| 按键快速查找 | 字典 |
| 需要保持顺序 | 字典(Python 3.7+有序)或列表 |
| 按索引访问 | 列表 |
| 存储同类型连续数据 | 列表 |
| 一对一映射关系 | 字典 |
Q3:怎么判断键是否在字典里?
python
person = {"name": "张三", "age": 18}
# 用 in
if "name" in person:
print("有name键")
# 用 get()(更安全)
if person.get("name"):
print("有name键且值不为空/0/False")
写在最后
字典是Python里最实用的数据结构之一:
- 键值对应,查找O(1)复杂度
- defaultdict 简化默认值处理
- 可以多层嵌套,模拟复杂数据结构
下一篇文章:Python 集合与元组,去重利器与不可变列表。
参考资料: