Python 基础详解:数据结构(Data Structures)—— 组织和管理数据的利器

一、引言:为什么数据结构如此重要?

在编程中,数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。它是组织和存储数据的方式,直接影响程序的效率、可读性和可维护性。

选择合适的数据结构可以:

  • 提高程序效率:更快地存取、插入、删除数据
  • 简化代码逻辑:更清晰地表达算法意图
  • 增强代码可维护性:易于修改、扩展和调试
  • 节省内存空间:合理利用资源

Python 提供了丰富的内置数据结构(如列表、字典、集合等),同时支持自定义复杂的数据结构(如链表、栈、队列等)。

💡 数据结构 + 算法 = 程序


二、核心数据结构概览

类别

数据结构

特点

序列类型

列表(List)、元组(Tuple)、字符串(String)、范围(Range)

有序的元素集合,支持索引访问

映射类型

字典(Dictionary)

键值对存储,支持快速查找

集合类型

集合(Set)、冻结集合(Frozen Set)

无序唯一元素,适合去重和成员测试

📌 本文将重点讲解最常用的数据结构及其操作。


三、列表(List)—— 动态数组

1. 定义与基本特性

列表是有序、可变的元素集合,可以存储不同类型的数据。

fruits = ["苹果", "香蕉", "橙子"]
numbers = [1, 2, 3]
mixed = ["Alice", 25, True]

✅ 支持异构数据类型,非常灵活。


2. 常用操作

2.1 索引与切片
print(fruits[0])      # "苹果"
print(fruits[-1])     # "橙子" (负索引:从末尾开始)
print(fruits[1:3])    # ["香蕉", "橙子"] (切片 [start:end),左闭右开)
print(fruits[:2])     # ["苹果", "香蕉"] (从开头到索引2之前)
print(fruits[1:])     # ["香蕉", "橙子"] (从索引1到最后)

📌 切片是 Python 中非常强大的特性,支持步长:fruits[::2] 表示每隔一个取一个。


2.2 修改元素
python
fruits[1] = "葡萄"
print(fruits)  # ["苹果", "葡萄", "橙子"]

✅ 列表是可变对象,可以直接通过索引修改。


2.3 添加与删除元素
# 添加
fruits.append("草莓")        # 在末尾添加
fruits.insert(1, "芒果")     # 在索引1处插入

# 删除
fruits.remove("苹果")        # 移除第一个匹配项
del fruits[0]               # 根据索引删除
popped = fruits.pop()       # 弹出并返回最后一个元素
popped_first = fruits.pop(0) # 弹出第一个元素

⚠️ remove() 只删除第一个匹配项;pop() 返回被删除的值。


2.4 排序与反转
numbers = [3, 1, 4, 1, 5]

numbers.sort()              # 原地升序排序 → [1, 1, 3, 4, 5]
numbers.reverse()           # 原地反转 → [5, 4, 3, 1, 1]

# 不改变原列表的排序
sorted_numbers = sorted(numbers, reverse=True)  # 返回降序新列表
reversed_list = list(reversed(numbers))         # 返回反转迭代器

✅ 推荐使用 sorted()reversed() 以避免副作用。


2.5 列表推导式(List Comprehension)

一种简洁创建列表的方式,语法清晰、性能优越。

# 生成平方数
squares = [x**2 for x in range(1, 6)]  # [1, 4, 9, 16, 25]

# 过滤偶数
evens = [x for x in range(10) if x % 2 == 0]  # [0, 2, 4, 6, 8]

# 多重循环
pairs = [(x, y) for x in [1,2] for y in ['a','b']] 
# [(1,'a'), (1,'b'), (2,'a'), (2,'b')]

✅ 比传统 for 循环更简洁高效。


四、元组(Tuple)—— 不可变序列

1. 定义与基本特性

元组与列表类似,但不可变,适合用于不希望被修改的数据(如坐标、配置项)。

point = (10, 20)
person = ("Alice", 25, "北京")
single = (42,)  # 单元素元组必须加逗号

✅ 不可变性带来安全性,可用于字典的键或集合的元素。


2. 常用操作

2.1 访问元素
print(point[0])  # 10
print(person[1]) # 25

📌 支持索引和切片,但不能修改。


2.2 解包(Unpacking)

一种优雅获取多个返回值的方式。

name, age, city = person
print(name, age, city)  # Alice 25 北京

# 忽略某些值
_, age, _ = person

# 扩展解包(Python 3+)
first, *rest = [1, 2, 3, 4]
print(first)  # 1
print(rest)   # [2, 3, 4]

✅ 广泛应用于函数返回值、循环遍历等场景。


五、字典(Dictionary)—— 键值映射

1. 定义与基本特性

字典是键值对的集合,键必须是唯一的且不可变(如字符串、数字、元组),值可以是任意类型。

student = {
    "name": "Bob",
    "age": 20,
    "courses": ["数学", "英语"]
}

✅ 基于哈希表实现,查找时间复杂度接近 O(1)。


2. 常用操作

2.1 访问与修改
rint(student["name"])     # Bob
student["age"] = 21        # 修改现有键
student["city"] = "上海"    # 新增键值对

⚠️ 访问不存在的键会抛出 KeyError


2.2 安全访问:get() 方法
# 使用 get 安全访问,避免 KeyError
print(student.get("phone", "未知"))  # 如果没有 'phone' 键,则返回 "未知"

✅ 推荐在不确定键是否存在时使用 get()


2.3 删除键值对
del student["courses"]           # 删除指定键
popped_value = student.pop("age") # 弹出并返回值
student.clear()                  # 清空所有键值对

📌 pop() 也可设置默认值:student.pop("grade", "未评级")


2.4 获取所有键、值、键值对
print(student.keys())     # dict_keys(['name', 'age'])
print(student.values())   # dict_values(['Bob', 21])
print(student.items())    # dict_items([('name', 'Bob'), ('age', 21)])

✅ 可用于遍历:

for key, value in student.items():
    print(f"{key}: {value}")

2.5 字典推导式
# 平方映射
squares = {x: x**2 for x in range(1, 6)}
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# 过滤长度大于3的键
filtered = {k: v for k, v in student.items() if len(k) > 3}

✅ 简洁高效地构建字典。


六、集合(Set)—— 无序唯一集合

1. 定义与基本特性

集合是无序、唯一元素的集合,常用于去重和成员测试。

unique_numbers = {1, 2, 3, 3, 4}  # {1, 2, 3, 4}
empty_set = set()  # 空集合(不能用 {},那是空字典)

✅ 基于哈希表实现,成员测试非常快(O(1))。


2. 常用操作

2.1 成员测试
print(2 in unique_numbers)  # True
print(5 not in unique_numbers)  # True

✅ 比列表快得多,尤其适合大数据量。


2.2 集合运算:并集、交集、差集、对称差
set1 = {1, 2, 3}
set2 = {3, 4, 5}

union_set = set1 | set2              # {1, 2, 3, 4, 5}
intersection_set = set1 & set2       # {3}
difference_set = set1 - set2         # {1, 2}
symmetric_difference_set = set1 ^ set2 # {1, 2, 4, 5}

# 也可以使用方法
set1.union(set2)
set1.intersection(set2)

✅ 数学集合运算的完美体现。


2.3 添加与删除
set1.add(4)
set1.update([5, 6])      # 批量添加
set1.remove(1)           # 删除,不存在则报错
set1.discard(10)         # 删除,不存在也不报错
popped = set1.pop()      # 随机弹出一个元素

discard()remove() 更安全。


七、冻结集合(Frozen Set)

frozenset 是不可变的集合,可以作为字典的键或集合的元素。

fs = frozenset([1, 2, 3])
d = {fs: "value"}  # 合法,因为 frozenset 是不可变的

✅ 适用于需要哈希的场景。


八、总结:数据结构核心要点

数据结构

特性

使用场景

列表 (List)

有序、可变、支持重复

动态数组、堆栈、队列、需要频繁修改的场景

元组 (Tuple)

有序、不可变、轻量

固定结构数据(如坐标)、函数返回多个值、作为字典键

字典 (Dict)

键值对、无序(Python 3.7+保持插入顺序)、快速查找

映射关系、缓存、配置管理、JSON 解析

集合 (Set)

无序、唯一、快速成员测试

去重、集合运算、黑名单/白名单


九、最佳实践与建议

建议

说明

✅ 优先使用内置数据结构

经过高度优化,性能好

✅ 根据场景选择合适结构

不要“万能列表”

✅ 使用推导式提升效率

简洁且性能优于循环

✅ 注意可变性带来的副作用

如函数参数传递可变对象

✅ 避免在循环中进行 O(n) 查找

用 set/dict 替代 list


十、动手练习

1. 创建一个字典,存储学生的姓名、年龄、课程,然后打印出所有课程名称

students = [
    {"name": "张三", "age": 20, "courses": ["数学", "物理"]},
    {"name": "李四", "age": 21, "courses": ["化学", "生物"]}
]

for student in students:
    print(f"{student['name']} 的课程: {', '.join(student['courses'])}")

2. 编写一个函数,接收一个列表作为参数,返回一个新的仅包含偶数的列表

def filter_even(numbers):
    return [num for num in numbers if num % 2 == 0]

numbers = [1, 2, 3, 4, 5, 6]
even_numbers = filter_even(numbers)
print(even_numbers)  # [2, 4, 6]

3. 使用集合去除重复的用户名单

usernames = ["alice", "bob", "alice", "charlie", "bob"]
unique_usernames = list(set(usernames))
print(unique_usernames)  # 顺序可能不同
# 若需保持顺序:
unique_ordered = list(dict.fromkeys(usernames))
print(unique_ordered)  # ['alice', 'bob', 'charlie']

🚀 学习建议

  1. 多实践:通过实际编写代码加深理解。
  2. 结合应用场景:思考每种数据结构最适合解决的问题类型。
  3. 深入学习高级应用
    • 生成器表达式(节省内存)
    • collections 模块(defaultdict, Counter, deque
    • itertools 模块(高效迭代工具)
  1. 阅读源码:学习标准库和优秀开源项目中的数据结构使用方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值