Python实战第7期:字典与集合

引言:为什么需要字典和集合?

在前面的课程中,我们学习了列表和元组,它们可以存储一组数据。但如果我们需要通过一个标识来快速查找数据呢?

比如:

  • 通过学号查找学生的成绩
  • 通过用户名查找用户信息
  • 通过城市名查找天气信息

这时候就需要用到字典。字典通过"键值对"的方式存储数据,可以快速查找。

而集合则用于存储不重复的元素,常用于去重和集合运算。


一、字典的键值对

1. 什么是字典

字典是Python中的一种数据结构,用于存储"键值对"(key-value pairs)。每个键对应一个值,通过键可以快速查找对应的值。

python 复制代码
# 创建字典
student = {
    "name": "小明",
    "age": 20,
    "score": 95
}
print(student)  # 输出:{'name': '小明', 'age': 20, 'score': 95}

# 空字典
empty_dict = {}
print(empty_dict)  # 输出:{}

# 使用dict()函数创建
student = dict(name="小明", age=20, score=95)
print(student)  # 输出:{'name': '小明', 'age': 20, 'score': 95}

💡 提示:字典的键必须是不可变类型(如字符串、数字、元组),值可以是任意类型。

2. 访问字典元素

python 复制代码
student = {
    "name": "小明",
    "age": 20,
    "score": 95
}

# 使用键访问值
print(student["name"])   # 输出:小明
print(student["age"])    # 输出:20
print(student["score"])  # 输出:95

# 使用get()方法(推荐)
print(student.get("name"))    # 输出:小明
print(student.get("gender"))  # 输出:None(键不存在时返回None)
print(student.get("gender", "未知"))  # 输出:未知(可以指定默认值)

💡 提示 :使用 [] 访问不存在的键会报错,使用 get() 方法更安全。

python 复制代码
# ❌ 使用[]访问不存在的键
# print(student["gender"])  # KeyError: 'gender'

# ✅ 使用get()方法
print(student.get("gender", "未知"))  # 输出:未知

3. 字典的特点

python 复制代码
student = {
    "name": "小明",
    "age": 20,
    "score": 95
}

# 1. 键必须是唯一的
student = {
    "name": "小明",
    "name": "小红"  # 后面的值会覆盖前面的
}
print(student)  # 输出:{'name': '小红'}

# 2. 键必须是不可变类型
# ✅ 可以使用字符串、数字、元组作为键
valid_dict = {
    "name": "小明",
    1: "数字键",
    (1, 2): "元组键"
}

# ❌ 不能使用列表、字典作为键
# invalid_dict = {
#     [1, 2]: "列表键"  # TypeError: unhashable type: 'list'
# }

# 3. 字典是无序的(Python 3.7+ 保持插入顺序)
print(student)  # 输出顺序与插入顺序一致

二、字典的增删改查

1. 增加元素

python 复制代码
student = {
    "name": "小明",
    "age": 20
}

# 直接赋值添加新键值对
student["score"] = 95
print(student)  # 输出:{'name': '小明', 'age': 20, 'score': 95}

# 使用update()方法添加多个键值对
student.update({"gender": "男", "city": "北京"})
print(student)  # 输出:{'name': '小明', 'age': 20, 'score': 95, 'gender': '男', 'city': '北京'}

# update()也可以修改已存在的键
student.update({"age": 21})
print(student)  # 输出:{'name': '小明', 'age': 21, 'score': 95, 'gender': '男', 'city': '北京'}

2. 删除元素

python 复制代码
student = {
    "name": "小明",
    "age": 20,
    "score": 95,
    "gender": "男"
}

# 使用del删除指定键值对
del student["gender"]
print(student)  # 输出:{'name': '小明', 'age': 20, 'score': 95}

# 使用pop()删除并返回值
age = student.pop("age")
print(age)      # 输出:20
print(student)  # 输出:{'name': '小明', 'score': 95}

# 使用popitem()删除最后一个键值对(Python 3.7+)
last_item = student.popitem()
print(last_item)  # 输出:('score', 95)
print(student)    # 输出:{'name': '小明'}

# 使用clear()清空字典
student.clear()
print(student)  # 输出:{}

💡 提示:

  • pop() 可以指定默认值,键不存在时返回默认值
  • popitem() 在空字典上调用会报错
python 复制代码
student = {"name": "小明"}
# 使用pop()指定默认值
gender = student.pop("gender", "未知")
print(gender)  # 输出:未知

3. 修改元素

python 复制代码
student = {
    "name": "小明",
    "age": 20,
    "score": 95
}

# 直接赋值修改
student["age"] = 21
student["score"] = 98
print(student)  # 输出:{'name': '小明', 'age': 21, 'score': 98}

# 使用update()修改多个值
student.update({"age": 22, "score": 100})
print(student)  # 输出:{'name': '小明', 'age': 22, 'score': 100}

4. 查询元素

python 复制代码
student = {
    "name": "小明",
    "age": 20,
    "score": 95
}

# 获取所有键
print(student.keys())      # 输出:dict_keys(['name', 'age', 'score'])
print(list(student.keys()))  # 输出:['name', 'age', 'score']

# 获取所有值
print(student.values())      # 输出:dict_values(['小明', 20, 95])
print(list(student.values()))  # 输出:['小明', 20, 95]

# 获取所有键值对
print(student.items())      # 输出:dict_items([('name', '小明'), ('age', 20), ('score', 95)])
print(list(student.items()))  # 输出:[('name', '小明'), ('age', 20), ('score', 95)]

# 判断键是否存在
print("name" in student)   # 输出:True
print("gender" in student)  # 输出:False

# 遍历字典
print("\n遍历键:")
for key in student:
    print(key)

print("\n遍历值:")
for value in student.values():
    print(value)

print("\n遍历键值对:")
for key, value in student.items():
    print(f"{key}: {value}")

5. 字典推导式

python 复制代码
# 基本语法:{键表达式: 值表达式 for 变量 in 序列}

# 创建1到5的平方字典
squares = {x: x**2 for x in range(1, 6)}
print(squares)  # 输出:{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# 从列表创建字典
names = ["张三", "李四", "王五"]
ages = [20, 21, 22]
student_dict = {name: age for name, age in zip(names, ages)}
print(student_dict)  # 输出:{'张三': 20, '李四': 21, '王五': 22}

# 筛选字典
scores = {"张三": 85, "李四": 92, "王五": 78, "赵六": 95}
high_scores = {name: score for name, score in scores.items() if score >= 90}
print(high_scores)  # 输出:{'李四': 92, '赵六': 95}

# 键值反转
original = {"a": 1, "b": 2, "c": 3}
reversed_dict = {value: key for key, value in original.items()}
print(reversed_dict)  # 输出:{1: 'a', 2: 'b', 3: 'c'}

三、嵌套字典

1. 字典嵌套字典

python 复制代码
# 学生信息
students = {
    "001": {
        "name": "张三",
        "age": 20,
        "scores": {
            "math": 85,
            "english": 92,
            "python": 95
        }
    },
    "002": {
        "name": "李四",
        "age": 21,
        "scores": {
            "math": 78,
            "english": 88,
            "python": 90
        }
    }
}

# 访问嵌套字典
print(students["001"]["name"])  # 输出:张三
print(students["001"]["scores"]["python"])  # 输出:95

# 修改嵌套字典
students["001"]["scores"]["python"] = 98
print(students["001"]["scores"]["python"])  # 输出:98

# 添加新的学生
students["003"] = {
    "name": "王五",
    "age": 22,
    "scores": {
        "math": 90,
        "english": 85,
        "python": 92
    }
}

# 遍历嵌套字典
for student_id, info in students.items():
    print(f"学号:{student_id}")
    print(f"姓名:{info['name']}")
    print(f"年龄:{info['age']}")
    print("成绩:")
    for subject, score in info['scores'].items():
        print(f"  {subject}: {score}")
    print()

2. 字典嵌套列表

python 复制代码
# 班级信息
classes = {
    "一班": {
        "students": ["张三", "李四", "王五"],
        "teacher": "刘老师"
    },
    "二班": {
        "students": ["赵六", "钱七", "孙八"],
        "teacher": "陈老师"
    }
}

# 访问
print(classes["一班"]["students"])  # 输出:['张三', '李四', '王五']
print(classes["一班"]["students"][0])  # 输出:张三

# 添加学生
classes["一班"]["students"].append("小明")
print(classes["一班"]["students"])  # 输出:['张三', '李四', '王五', '小明']

四、集合的基本操作

1. 什么是集合

集合 是一个无序、不重复的元素集,用花括号 {} 表示。

python 复制代码
# 创建集合
fruits = {"苹果", "香蕉", "橙子", "苹果"}
print(fruits)  # 输出:{'苹果', '香蕉', '橙子'}(自动去重)

# 空集合(注意:{}创建的是空字典,不是空集合)
empty_set = set()
print(empty_set)  # 输出:set()

# 使用set()函数创建
numbers = set([1, 2, 3, 2, 1])
print(numbers)  # 输出:{1, 2, 3}

# 从字符串创建
chars = set("hello")
print(chars)  # 输出:{'h', 'e', 'l', 'o'}

💡 提示:集合中的元素必须是不可变类型(如数字、字符串、元组)。

2. 集合的基本操作

python 复制代码
fruits = {"苹果", "香蕉", "橙子"}

# 添加元素
fruits.add("葡萄")
print(fruits)  # 输出:{'苹果', '香蕉', '橙子', '葡萄'}

# 添加多个元素
fruits.update(["西瓜", "芒果"])
print(fruits)  # 输出:{'苹果', '香蕉', '橙子', '葡萄', '西瓜', '芒果'}

# 删除元素
fruits.remove("香蕉")  # 元素不存在会报错
print(fruits)  # 输出:{'苹果', '橙子', '葡萄', '西瓜', '芒果'}

fruits.discard("芒果")  # 元素不存在不会报错
print(fruits)  # 输出:{'苹果', '橙子', '葡萄', '西瓜'}

# pop()删除并返回一个元素
removed = fruits.pop()
print(removed)  # 输出:苹果(随机)
print(fruits)   # 输出:{'橙子', '葡萄', '西瓜'}

# 清空集合
fruits.clear()
print(fruits)  # 输出:set()

3. 集合运算

python 复制代码
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}

# 交集(两个集合都有的元素)
print(set1 & set2)           # 输出:{4, 5}
print(set1.intersection(set2))  # 输出:{4, 5}

# 并集(两个集合的所有元素,去重)
print(set1 | set2)           # 输出:{1, 2, 3, 4, 5, 6, 7, 8}
print(set1.union(set2))      # 输出:{1, 2, 3, 4, 5, 6, 7, 8}

# 差集(set1有但set2没有的元素)
print(set1 - set2)           # 输出:{1, 2, 3}
print(set1.difference(set2))  # 输出:{1, 2, 3}

# 对称差集(两个集合中不共有的元素)
print(set1 ^ set2)           # 输出:{1, 2, 3, 6, 7, 8}
print(set1.symmetric_difference(set2))  # 输出:{1, 2, 3, 6, 7, 8}

4. 集合的比较

python 复制代码
set1 = {1, 2, 3}
set2 = {1, 2, 3, 4, 5}
set3 = {1, 2, 3}

# 子集(set1是否是set2的子集)
print(set1 <= set2)  # 输出:True
print(set1.issubset(set2))  # 输出:True

# 超集(set2是否是set1的超集)
print(set2 >= set1)  # 输出:True
print(set2.issuperset(set1))  # 输出:True

# 真子集(set1是set2的子集,但不相等)
print(set1 < set2)  # 输出:True
print(set1 < set3)  # 输出:False(相等,不是真子集)

# 相等
print(set1 == set3)  # 输出:True

5. 集合推导式

python 复制代码
# 基本语法:{表达式 for 变量 in 序列}

# 创建平方集合
squares = {x**2 for x in range(1, 6)}
print(squares)  # 输出:{1, 4, 9, 16, 25}

# 从列表创建集合(去重)
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique_squares = {x**2 for x in numbers}
print(unique_squares)  # 输出:{1, 4, 9, 16}

# 筛选集合
numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
evens = {x for x in numbers if x % 2 == 0}
print(evens)  # 输出:{2, 4, 6, 8, 10}

五、字典与集合的应用

1. 字典的应用场景

python 复制代码
# 1. 统计词频
text = "hello world hello python world hello"
words = text.split()
word_count = {}

for word in words:
    if word in word_count:
        word_count[word] += 1
    else:
        word_count[word] = 1

print(word_count)  # 输出:{'hello': 3, 'world': 2, 'python': 1}

# 使用get()简化
word_count = {}
for word in words:
    word_count[word] = word_count.get(word, 0) + 1
print(word_count)  # 输出:{'hello': 3, 'world': 2, 'python': 1}

# 2. 缓存/记忆化
cache = {}

def fibonacci(n):
    if n in cache:
        return cache[n]
    
    if n <= 1:
        result = n
    else:
        result = fibonacci(n-1) + fibonacci(n-2)
    
    cache[n] = result
    return result

print(fibonacci(10))  # 输出:55

# 3. 配置管理
config = {
    "database": {
        "host": "localhost",
        "port": 3306,
        "user": "root",
        "password": "123456"
    },
    "server": {
        "host": "0.0.0.0",
        "port": 8080
    }
}

# 4. JSON数据处理
import json

data = {
    "name": "小明",
    "age": 20,
    "scores": [85, 92, 95]
}

# 字典转JSON字符串
json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(json_str)

# JSON字符串转字典
parsed_data = json.loads(json_str)
print(parsed_data)

2. 集合的应用场景

python 复制代码
# 1. 去重
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique_numbers = list(set(numbers))
print(unique_numbers)  # 输出:[1, 2, 3, 4]

# 2. 判断成员关系(比列表快)
valid_users = {"user1", "user2", "user3", "user4", "user5"}
print("user1" in valid_users)  # 输出:True(O(1)时间复杂度)

# 3. 找出两个列表的共同元素
list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 6, 7, 8]
common = set(list1) & set(list2)
print(common)  # 输出:{4, 5}

# 4. 找出两个列表的不同元素
diff = set(list1) ^ set(list2)
print(diff)  # 输出:{1, 2, 3, 6, 7, 8}

# 5. 合并多个列表并去重
list1 = [1, 2, 3]
list2 = [2, 3, 4]
list3 = [3, 4, 5]
merged = list(set(list1) | set(list2) | set(list3))
print(merged)  # 输出:[1, 2, 3, 4, 5]

六、实战练习

练习1:学生成绩管理系统

python 复制代码
# 学生成绩字典
students = {
    "001": {"name": "张三", "scores": {"math": 85, "english": 92, "python": 95}},
    "002": {"name": "李四", "scores": {"math": 78, "english": 88, "python": 90}},
    "003": {"name": "王五", "scores": {"math": 90, "english": 85, "python": 92}}
}

# 计算每个学生的平均分
for student_id, info in students.items():
    scores = info["scores"].values()
    average = sum(scores) / len(scores)
    print(f"{info['name']}的平均分:{average:.1f}")

# 找出Python成绩最高的学生
max_score = 0
top_student = ""
for student_id, info in students.items():
    if info["scores"]["python"] > max_score:
        max_score = info["scores"]["python"]
        top_student = info["name"]

print(f"\nPython成绩最高:{top_student}({max_score}分)")

# 统计各科平均分
subjects = ["math", "english", "python"]
for subject in subjects:
    scores = [info["scores"][subject] for info in students.values()]
    average = sum(scores) / len(scores)
    print(f"{subject}平均分:{average:.1f}")

练习2:词频统计

python 复制代码
# 文本
text = """
Python是一种广泛使用的高级编程语言。
Python的设计哲学强调代码的可读性和简洁的语法。
Python支持多种编程范式,包括面向对象、命令式、函数式和过程式编程。
Python被广泛应用于Web开发、数据科学、人工智能等领域。
"""

# 清理文本
text = text.replace("。", "").replace(",", "").replace("、", "")
words = text.split()

# 统计词频
word_count = {}
for word in words:
    word_count[word] = word_count.get(word, 0) + 1

# 按频率排序
sorted_words = sorted(word_count.items(), key=lambda x: x[1], reverse=True)

print("词频统计(前10):")
for word, count in sorted_words[:10]:
    print(f"{word}:{count}次")

# 找出出现次数最多的词
most_common = sorted_words[0]
print(f"\n出现最多的词:{most_common[0]}({most_common[1]}次)")

练习3:集合运算应用

python 复制代码
# 两个班级的学生名单
class1 = {"张三", "李四", "王五", "赵六", "钱七"}
class2 = {"孙八", "周九", "吴十", "赵六", "钱七"}

# 1. 找出两个班级都有的学生(可能转班)
common_students = class1 & class2
print(f"两个班级都有的学生:{common_students}")

# 2. 找出一班独有的学生
class1_only = class1 - class2
print(f"一班独有的学生:{class1_only}")

# 3. 找出所有学生(去重)
all_students = class1 | class2
print(f"所有学生:{all_students}")
print(f"总人数:{len(all_students)}")

# 4. 找出只在其中一个班级的学生
unique_students = class1 ^ class2
print(f"只在一个班级的学生:{unique_students}")

练习4:JSON数据处理

python 复制代码
import json

# 模拟从API获取的数据
api_response = """
{
    "status": "success",
    "data": {
        "users": [
            {"id": 1, "name": "张三", "age": 20, "city": "北京"},
            {"id": 2, "name": "李四", "age": 25, "city": "上海"},
            {"id": 3, "name": "王五", "age": 22, "city": "广州"}
        ],
        "total": 3
    }
}
"""

# 解析JSON
data = json.loads(api_response)

# 提取用户信息
users = data["data"]["users"]

# 1. 打印所有用户信息
print("用户列表:")
for user in users:
    print(f"ID: {user['id']}, 姓名: {user['name']}, 年龄: {user['age']}, 城市: {user['city']}")

# 2. 找出年龄最大的用户
oldest_user = max(users, key=lambda x: x["age"])
print(f"\n年龄最大的用户:{oldest_user['name']}({oldest_user['age']}岁)")

# 3. 统计各城市用户数
city_count = {}
for user in users:
    city = user["city"]
    city_count[city] = city_count.get(city, 0) + 1

print("\n各城市用户数:")
for city, count in city_count.items():
    print(f"{city}:{count}人")

# 4. 将处理后的数据保存为JSON
result = {
    "status": "success",
    "oldest_user": oldest_user,
    "city_count": city_count
}

result_json = json.dumps(result, ensure_ascii=False, indent=2)
print("\n处理结果:")
print(result_json)

七、常见问题与排错

问题1:字典键不存在报错

原因 :使用 [] 访问不存在的键 解决方法 :使用 get() 方法或先判断键是否存在

python 复制代码
student = {"name": "小明", "age": 20}

# ❌ 错误
# print(student["gender"])  # KeyError: 'gender'

# ✅ 正确方法1:使用get()
print(student.get("gender", "未知"))  # 输出:未知

# ✅ 正确方法2:先判断
if "gender" in student:
    print(student["gender"])
else:
    print("未知")

问题2:修改字典时迭代报错

原因 :在遍历字典时修改字典 解决方法:先收集要修改的键,遍历完再修改

python 复制代码
student = {"name": "小明", "age": 20, "score": 95}

# ❌ 错误:在遍历时修改字典
# for key in student:
#     if key == "age":
#         del student[key]  # RuntimeError: dictionary changed size during iteration

# ✅ 正确:先收集要删除的键
keys_to_delete = []
for key in student:
    if key == "age":
        keys_to_delete.append(key)

for key in keys_to_delete:
    del student[key]

print(student)  # 输出:{'name': '小明', 'score': 95}

问题3:集合元素不可变

原因 :集合的元素必须是不可变类型 解决方法:使用元组代替列表

python 复制代码
# ❌ 错误:列表不能作为集合元素
# invalid_set = {[1, 2], [3, 4]}  # TypeError: unhashable type: 'list'

# ✅ 正确:使用元组
valid_set = {(1, 2), (3, 4)}
print(valid_set)  # 输出:{(1, 2), (3, 4)}

八、本篇小结

今天,我们完成了以下学习内容:

  1. 字典的键值对:

    • 使用 {} 或 dict() 创建字典
    • 键必须是不可变类型,值可以是任意类型
    • 通过键访问值,使用 get() 更安全
  2. 字典的增删改查:

    • 增加:直接赋值、update()
    • 删除:del、pop()、popitem()、clear()
    • 修改:直接赋值、update()
    • 查询:keys()、values()、items()、遍历
  3. 集合的基本操作:

    • 使用 {} 或 set() 创建集合
    • 添加:add()、update()
    • 删除:remove()、discard()、pop()、clear()
    • 集合运算:交集、并集、差集、对称差集

请记住这三个结论:

  1. 字典通过键查找值:适合存储有对应关系的数据
  2. 集合自动去重:适合存储不重复的元素,支持集合运算
  3. 字典和集合查找速度快:时间复杂度为O(1)

下期预告

在第8期中,我们将学习Python的函数,包括:

  • 函数的定义和调用
  • 参数和返回值
  • 变量的作用域
  • 匿名函数和高阶函数

敬请期待!


✍坚持原创,求关注,点赞,收藏

相关推荐
2603_965148111 小时前
电商选品调研:通过关键词搜索API获取市场热销商品,结合商品详情API分析竞品卖点与定价
开发语言·数据库·人工智能·python·信息可视化
码事漫谈1 小时前
DeepSeek 又更新!但怎么有个分数往下掉?
后端
吃饱了得干活1 小时前
用 PageHelper 同步数据到 ES:能跑,但这几个坑得先知道
后端·elasticsearch
金銀銅鐵2 小时前
[Java] 借助GUI展示class文件的内容(v1.0版本)
jvm·后端·ai编程
皮皮林5512 小时前
Java 导出 Excel 利器:JXLS
后端
吃饱了得干活2 小时前
从 LIKE 查询到毫秒级搜索:Elasticsearch 核心原理与 Java 实战
后端·elasticsearch
xixiaoyunya2 小时前
Python 异步编程入门:用 asyncio 轻松实现并发任务
开发语言·python·php
把我格子衫拿来2 小时前
Dice 很高就够了吗?分割评价中的 IoU、表面距离与 HD95
python·图像分割·模型评估·医学影像·dice