引言
在前面两章中,我们学习了Python的基础语法、控制结构和函数。这些知识为我们编写程序打下了坚实的基础。然而,在实际编程中,我们经常需要处理大量的数据,这就需要使用合适的数据结构来组织和管理这些数据。
Python提供了多种内置的数据结构,每种都有其独特的特点和适用场景。正确选择和使用数据结构不仅能提高程序的效率,还能让代码更加清晰易懂。
在本章中,我们将深入学习Python中最常用的四种内置数据结构:列表(List)、元组(Tuple)、字典(Dictionary)和集合(Set)。我们将探讨它们的特点、使用方法以及在实际编程中的应用场景。
学习目标
完成本章学习后,你将能够:
- 理解并熟练使用列表(List)进行数据存储和操作
- 掌握元组(Tuple)的特点及其与列表的区别
- 熟练使用字典(Dictionary)进行键值对数据的管理
- 理解集合(Set)的特点及其在去重和集合运算中的应用
- 根据不同场景选择合适的数据结构
- 掌握各种数据结构的常用方法和操作
- 编写高效的数据处理程序
核心知识点讲解
列表(List)
列表是Python中最常用的数据结构之一,它是一个有序的可变集合,可以存储不同类型的数据。
创建列表
# 创建空列表
empty_list = []
# 创建包含元素的列表
numbers = [1, 2, 3, 4, 5]
fruits = ["苹果", "香蕉", "橙子"]
mixed = [1, "hello", 3.14, True]
# 使用list()函数创建列表
chars = list("Python") # ['P', 'y', 't', 'h', 'o', 'n']
访问列表元素
fruits = ["苹果", "香蕉", "橙子", "葡萄"]
# 通过索引访问元素(从0开始)
print(fruits[0]) # 输出: 苹果
print(fruits[2]) # 输出: 橙子
# 负索引(从-1开始,表示倒数第一个元素)
print(fruits[-1]) # 输出: 葡萄
print(fruits[-2]) # 输出: 橙子
# 切片操作
print(fruits[1:3]) # 输出: ['香蕉', '橙子']
print(fruits[:2]) # 输出: ['苹果', '香蕉']
print(fruits[2:]) # 输出: ['橙子', '葡萄']
修改列表
fruits = ["苹果", "香蕉", "橙子"]
# 修改单个元素
fruits[1] = "草莓"
print(fruits) # 输出: ['苹果', '草莓', '橙子']
# 修改多个元素
fruits[1:3] = ["葡萄", "柠檬"]
print(fruits) # 输出: ['苹果', '葡萄', '柠檬']
列表常用方法
fruits = ["苹果", "香蕉", "橙子"]
# 添加元素
fruits.append("葡萄") # 在末尾添加元素
fruits.insert(1, "草莓") # 在指定位置插入元素
fruits.extend(["柠檬", "西瓜"]) # 添加多个元素
# 删除元素
fruits.remove("香蕉") # 删除指定元素
removed_fruit = fruits.pop() # 删除并返回最后一个元素
removed_fruit = fruits.pop(0) # 删除并返回指定位置的元素
fruits.clear() # 清空列表
# 查找元素
fruits = ["苹果", "香蕉", "橙子", "苹果"]
print(fruits.index("香蕉")) # 输出: 1
print(fruits.count("苹果")) # 输出: 2
# 排序
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
numbers.sort() # 升序排序
numbers.sort(reverse=True) # 降序排序
# 反转
numbers.reverse()
# 复制列表
original = [1, 2, 3]
copy1 = original.copy() # 浅拷贝
copy2 = original[:] # 切片复制
copy3 = list(original) # 使用list()函数
列表推导式
列表推导式是一种简洁创建列表的方法:
# 基本用法
squares = [x**2 for x in range(10)]
print(squares) # 输出: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 带条件的列表推导式
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares) # 输出: [0, 4, 16, 36, 64]
# 嵌套列表推导式
matrix = [[i*j for j in range(1, 4)] for i in range(1, 4)]
print(matrix) # 输出: [[1, 2, 3], [2, 4, 6], [3, 6, 9]]
元组(Tuple)
元组与列表类似,但它是不可变的(immutable),一旦创建就不能修改。
创建元组
# 创建空元组
empty_tuple = ()
# 创建包含元素的元组
point = (3, 4)
person = ("张三", 25, "北京")
# 单元素元组需要加逗号
single = (42,) # 注意逗号
# 不使用括号也可以创建元组
coordinates = 1, 2, 3
访问元组元素
person = ("张三", 25, "北京")
# 通过索引访问元素
print(person[0]) # 输出: 张三
print(person[-1]) # 输出: 北京
# 切片操作
print(person[1:]) # 输出: (25, '北京')
元组的特点
# 元组不可变
point = (3, 4)
# point[0] = 5 # 这会报错: TypeError
# 元组可以作为字典的键
locations = {(0, 0): "原点", (1, 1): "第一象限"}
# 元组可以 unpacking
x, y = point
print(x, y) # 输出: 3 4
# 函数可以返回多个值(实际上是返回元组)
def get_name_age():
return "李四", 30
name, age = get_name_age()
字典(Dictionary)
字典是一种可变的、无序的键值对集合。每个键值对由键和值组成,通过键可以快速访问对应的值。
创建字典
# 创建空字典
empty_dict = {}
# 创建包含键值对的字典
student = {"name": "张三", "age": 20, "major": "计算机科学"}
scores = {1: 95, 2: 87, 3: 92}
# 使用dict()函数创建字典
person = dict(name="李四", age=25, city="上海")
# 使用键值对列表创建字典
items = [("name", "王五"), ("age", 22)]
info = dict(items)
访问和修改字典
student = {"name": "张三", "age": 20, "major": "计算机科学"}
# 通过键访问值
print(student["name"]) # 输出: 张三
# 使用get()方法(更安全)
print(student.get("name")) # 输出: 张三
print(student.get("grade", "N/A")) # 输出: N/A(键不存在时返回默认值)
# 修改值
student["age"] = 21
# 添加新的键值对
student["grade"] = "大二"
# 删除键值对
del student["major"]
removed_value = student.pop("age") # 删除并返回值
student.clear() # 清空字典
字典常用方法
student = {"name": "张三", "age": 20, "major": "计算机科学"}
# 获取所有键、值、键值对
keys = student.keys()
values = student.values()
items = student.items()
# 检查键是否存在
if "name" in student:
print("姓名:", student["name"])
# 更新字典
additional_info = {"city": "北京", "phone": "123456789"}
student.update(additional_info)
# 字典推导式
squares = {x: x**2 for x in range(5)}
print(squares) # 输出: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
遍历字典
student = {"name": "张三", "age": 20, "major": "计算机科学"}
# 遍历键
for key in student:
print(key)
# 遍历值
for value in student.values():
print(value)
# 遍历键值对
for key, value in student.items():
print(f"{key}: {value}")
集合(Set)
集合是一个无序的不重复元素序列。集合支持数学上的集合运算,如并集、交集、差集等。
创建集合
# 创建空集合
empty_set = set() # 注意不能用{}
# 创建包含元素的集合
numbers = {1, 2, 3, 4, 5}
fruits = {"苹果", "香蕉", "橙子"}
# 使用set()函数创建集合
chars = set("hello") # {'h', 'e', 'l', 'o'}
集合操作
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
# 添加和删除元素
set1.add(6)
set1.remove(1) # 如果元素不存在会报错
set1.discard(10) # 如果元素不存在不会报错
popped = set1.pop() # 随机删除并返回一个元素
# 集合运算
union = set1 | set2 # 并集
intersection = set1 & set2 # 交集
difference = set1 - set2 # 差集
symmetric_diff = set1 ^ set2 # 对称差集
# 使用方法形式
union = set1.union(set2)
intersection = set1.intersection(set2)
difference = set1.difference(set2)
# 子集和超集
set3 = {1, 2}
print(set3.issubset(set1)) # 检查是否为子集
print(set1.issuperset(set3)) # 检查是否为超集
集合的特点
# 自动去重
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique_numbers = list(set(numbers))
print(unique_numbers) # 输出: [1, 2, 3, 4](顺序可能不同)
# 成员检查(比列表快)
large_set = set(range(1000000))
print(999999 in large_set) # 非常快的检查
代码示例与实战
示例1:学生成绩管理系统
class StudentManager:
def __init__(self):
self.students = {} # 使用字典存储学生信息
def add_student(self, student_id, name, scores=None):
"""添加学生"""
if scores is None:
scores = []
self.students[student_id] = {
"name": name,
"scores": scores
}
print(f"已添加学生: {name} (ID: {student_id})")
def add_score(self, student_id, score):
"""为学生添加成绩"""
if student_id in self.students:
self.students[student_id]["scores"].append(score)
print(f"已为学生 {self.students[student_id]['name']} 添加成绩: {score}")
else:
print("学生不存在")
def get_average(self, student_id):
"""计算学生平均成绩"""
if student_id in self.students:
scores = self.students[student_id]["scores"]
if scores:
return sum(scores) / len(scores)
else:
return 0
else:
return None
def get_top_students(self, n=3):
"""获取成绩最好的n名学生"""
averages = []
for student_id, info in self.students.items():
avg = self.get_average(student_id)
if avg > 0: # 只考虑有成绩的学生
averages.append((info["name"], avg))
# 按平均分降序排序
averages.sort(key=lambda x: x[1], reverse=True)
return averages[:n]
def display_all_students(self):
"""显示所有学生信息"""
if not self.students:
print("暂无学生信息")
return
print("\n=== 学生信息 ===")
for student_id, info in self.students.items():
avg = self.get_average(student_id)
print(f"ID: {student_id}, 姓名: {info['name']}, "
f"成绩: {info['scores']}, 平均分: {avg:.2f}")
print("=" * 30)
def main():
manager = StudentManager()
# 添加学生
manager.add_student("001", "张三")
manager.add_student("002", "李四")
manager.add_student("003", "王五")
# 添加成绩
manager.add_score("001", 85)
manager.add_score("001", 92)
manager.add_score("002", 78)
manager.add_score("002", 88)
manager.add_score("003", 95)
manager.add_score("003", 87)
# 显示所有学生
manager.display_all_students()
# 显示前三名学生
top_students = manager.get_top_students(3)
print("\n=== 成绩排名 ===")
for i, (name, avg) in enumerate(top_students, 1):
print(f"第{i}名: {name}, 平均分: {avg:.2f}")
if __name__ == "__main__":
main()
示例2:词汇统计器
import string
def analyze_text(text):
"""分析文本,统计词汇信息"""
# 转换为小写并移除标点符号
translator = str.maketrans('', '', string.punctuation)
clean_text = text.lower().translate(translator)
# 分割成单词列表
words = clean_text.split()
# 使用字典统计词频
word_count = {}
for word in words:
word_count[word] = word_count.get(word, 0) + 1
# 使用集合找出唯一词汇
unique_words = set(words)
# 统计信息
total_words = len(words)
unique_word_count = len(unique_words)
# 找出最常见的词汇
most_common = sorted(word_count.items(), key=lambda x: x[1], reverse=True)[:5]
return {
"total_words": total_words,
"unique_words": unique_word_count,
"word_count": word_count,
"unique_word_set": unique_words,
"most_common": most_common
}
def display_analysis(analysis):
"""显示分析结果"""
print("=== 文本分析结果 ===")
print(f"总词数: {analysis['total_words']}")
print(f"唯一词汇数: {analysis['unique_words']}")
print(f"词汇重复率: {(analysis['total_words'] - analysis['unique_words']) / analysis['total_words'] * 100:.2f}%")
print("\n最常见的5个词:")
for word, count in analysis['most_common']:
print(f" {word}: {count}次")
print(f"\n前20个唯一词汇: {list(analysis['unique_word_set'])[:20]}")
def main():
sample_text = """
Python is a high-level programming language. Python is easy to learn and powerful.
It is widely used in web development, data science, artificial intelligence,
and many other fields. Python has a simple syntax that makes it readable and
maintainable. Many developers love Python because of its versatility and
extensive library support.
"""
analysis = analyze_text(sample_text)
display_analysis(analysis)
if __name__ == "__main__":
main()
示例3:购物车系统
class ShoppingCart:
def __init__(self):
# 使用字典存储商品信息:商品名 -> (价格, 数量)
self.items = {}
def add_item(self, name, price, quantity=1):
"""添加商品到购物车"""
if name in self.items:
# 如果商品已存在,增加数量
current_price, current_quantity = self.items[name]
self.items[name] = (price, current_quantity + quantity)
else:
# 添加新商品
self.items[name] = (price, quantity)
print(f"已添加 {quantity} 个 {name} 到购物车")
def remove_item(self, name, quantity=None):
"""从购物车移除商品"""
if name not in self.items:
print(f"购物车中没有 {name}")
return
current_price, current_quantity = self.items[name]
if quantity is None or quantity >= current_quantity:
# 移除所有该商品
del self.items[name]
print(f"已从购物车移除所有 {name}")
else:
# 只移除指定数量
self.items[name] = (current_price, current_quantity - quantity)
print(f"已从购物车移除 {quantity} 个 {name}")
def update_quantity(self, name, new_quantity):
"""更新商品数量"""
if name in self.items:
current_price, _ = self.items[name]
if new_quantity <= 0:
del self.items[name]
print(f"已从购物车移除 {name}")
else:
self.items[name] = (current_price, new_quantity)
print(f"已更新 {name} 的数量为 {new_quantity}")
else:
print(f"购物车中没有 {name}")
def get_total_price(self):
"""计算总价"""
total = 0
for price, quantity in self.items.values():
total += price * quantity
return total
def display_cart(self):
"""显示购物车内容"""
if not self.items:
print("购物车为空")
return
print("\n=== 购物车 ===")
total_items = 0
for name, (price, quantity) in self.items.items():
subtotal = price * quantity
print(f"{name}: ¥{price:.2f} x {quantity} = ¥{subtotal:.2f}")
total_items += quantity
print("-" * 30)
print(f"总计: ¥{self.get_total_price():.2f} ({total_items} 件商品)")
print("=" * 30)
def main():
cart = ShoppingCart()
# 添加商品
cart.add_item("苹果", 5.0, 3)
cart.add_item("香蕉", 3.5, 2)
cart.add_item("橙子", 4.0, 5)
cart.add_item("苹果", 5.0, 2) # 再添加苹果
# 显示购物车
cart.display_cart()
# 更新数量
cart.update_quantity("香蕉", 5)
# 移除部分商品
cart.remove_item("橙子", 2)
# 再次显示购物车
cart.display_cart()
if __name__ == "__main__":
main()
小结与回顾
在本章中,我们深入学习了Python中的四种主要内置数据结构:
-
列表(List):
- 有序、可变的数据集合
- 支持索引、切片、增删改查等操作
- 提供丰富的内置方法
- 支持列表推导式
-
元组(Tuple):
- 有序、不可变的数据集合
- 可以作为字典的键
- 支持unpacking操作
- 比列表更节省内存
-
字典(Dictionary):
- 键值对数据结构
- 通过键快速访问值
- 支持各种集合操作
- 提供高效的查找性能
-
集合(Set):
- 无序、不重复元素集合
- 支持数学集合运算
- 自动去重功能
- 快速成员检查
通过实际的代码示例,我们不仅掌握了这些数据结构的基本用法,还学会了如何在实际项目中应用它们。正确选择和使用数据结构是编写高效Python程序的关键。
在下一章中,我们将学习面向对象编程的基础知识,包括类和对象的概念,这将帮助我们编写更加模块化和可维护的代码。
练习与挑战
基础练习
- 创建一个程序,使用列表存储一周的天气温度,计算平均温度、最高温度和最低温度。
- 编写一个函数,接受一个字符串列表,返回其中最长的字符串。
- 创建一个字典来存储国家和首都的对应关系,实现添加、查询、删除功能。
- 编写一个程序,使用集合找出两个文本文件中的共同词汇。
进阶挑战
- 实现一个简单的图书馆管理系统,使用字典存储图书信息,支持借阅、归还、查询等功能。
- 创建一个联系人管理系统,使用列表和字典的组合来存储联系人信息,支持增删改查。
- 编写一个程序,模拟电商网站的商品分类系统,使用嵌套字典和列表来组织商品数据。
- 实现一个简单的任务管理系统,使用列表存储任务,支持任务的添加、完成、删除和优先级排序。
思考题
- 在什么情况下应该使用列表而不是元组?
- 字典和列表在性能上有何区别?分别适用于什么场景?
- 集合相比列表有哪些优势?在什么情况下使用集合更合适?
- 如何选择合适的数据结构来优化程序性能?
扩展阅读
- Python官方文档 - 数据结构 - 官方文档中关于内置数据结构的详细介绍
- Python官方文档 - 序列类型 - 列表和元组的详细说明
- Python官方文档 - 映射类型 - 字典的详细说明
- Python官方文档 - 集合类型 - 集合的详细说明
- 《流畅的Python》- 深入理解Python数据结构的经典书籍
- Real Python - Python Data Structures - 关于Python数据结构的详细教程
通过本章的学习,你应该已经掌握了Python中四种主要数据结构的特点和使用方法。这些知识将帮助你更有效地组织和处理数据。在下一章中,我们将学习面向对象编程的基础知识,这是现代编程的重要范式。