跳到主要内容Python算法
Python 数据结构详解:序列与集合
综述由AI生成详细讲解了 Python 核心数据结构,包括字符串、列表、字典、集合和元组。重点阐述了可变与不可变对象的区别及其影响,涵盖了索引切片、常用方法、推导式及浅拷贝陷阱等关键知识点。通过代码示例展示了各数据结构的创建、操作及最佳实践,帮助开发者高效组织和管理数据。
孤勇者27 浏览 Python 数据结构详解:序列与集合
引言:数据需要'容器'
上一章我们学会了 Python 的基本语法,能定义变量、处理简单的数字和字符串。但现实世界的数据远不止单个值——比如一个班级的学生名单、商品的库存信息、网站的访问日志……这些都需要用数据结构来组织和存储。
Python 内置了多种强大的数据结构,它们就像不同形状的容器,有的能装一串有序的东西(列表),有的能通过名字快速查找(字典),有的能保证元素唯一(集合)。掌握它们,你的编程能力将瞬间提升一个档次。
本章我们就来逐个击破:字符串(深入)、列表、字典、集合、元组,并理解一个核心概念——可变与不可变。
一、可变与不可变:理解对象的'性格'
在深入具体数据结构之前,先搞清楚一个关键问题:对象能不能被修改?
- 不可变对象:创建后内容不能改变。一旦修改,Python 会创建一个新对象。
- 可变对象:创建后内容可以原地修改,内存地址不变。
a = 10
print(id(a))
a += 1
print(id(a))
lst = [1, 2, 3]
print(id(lst))
lst.append(4)
print(id(lst))
理解这个对后续学习至关重要,因为可变对象的方法往往没有返回值(就地修改),而不可变对象的方法会返回新对象。
二、字符串(深入):不只是文本
第一章我们学会了字符串的基本操作,现在给它来一次'深度体检'。记住:字符串是不可变序列,所以所有'修改'操作都是返回新字符串。
1. 索引与切片(序列通用操作)
字符串里的每个字符都有位置(索引),从 0 开始。
s = "Python"
print(s[0])
print(s[-1])
切片:[start:stop:step] 截取子串(含 start,不含 stop)
s = "Hello, Python"
print(s[7:13])
print(s[:5])
print(s[7:])
print(s[::2])
print(s[::-1])
2. 常用方法(挑几个最实用的)
| 方法 | 作用 | 示例 |
|---|
split() | 按分隔符拆成列表 | "a,b,c".split(",") → ['a','b','c'] |
join() | 将列表合并为字符串 | "-".join(['a','b','c']) → "a-b-c" |
replace() | 替换子串 | "Hello world".replace("world","Python") → "Hello Python" |
strip() | 去除两端空白字符 | " hello ".strip() → "hello" |
upper()/lower() | 大小写转换 | "Python".upper() → "PYTHON" |
startswith()/endswith() | 判断开头/结尾 | "hello.py".endswith(".py") → True |
find()/index() | 查找子串位置 | "hello".find("l") → 2(找不到返回 -1);index() 找不到抛异常 |
count() | 统计出现次数 | "abracadabra".count("a") → 5 |
冷知识:split() 如果不给参数,会按任意空白字符分割(空格、换行、制表符),并且会压缩连续空白。而 split(' ') 则只按单个空格分割。
3. 字符串格式化:让输出更优雅
老派写法:% 格式化(类似 C 语言)
name = "Alice"
age = 25
print("我是 %s,今年 %d 岁"%(name, age))
中年写法:str.format()
print("我是 {},今年 {} 岁".format(name, age))
print("我是 {name},今年 {age} 岁".format(name=name, age=age))
现代写法:f-string(Python 3.6+ 推荐)
print(f"我是 {name},今年 {age} 岁")
print(f"3.14159 保留两位小数:{3.14159:.2f}")
f-string 简洁直观,还能在花括号里写表达式,必学!
三、列表:Python 的'万能背包'
列表是可变序列,能装任意类型的数据(甚至可以混合类型),用方括号 [] 表示。
1. 创建列表
fruits = ["apple", "banana", "orange"]
mixed = [1, "hello", 3.14, True]
empty = []
list_from_str = list("Python")
squares = [x**2 for x in range(10)]
evens = [x for x in range(20) if x % 2 == 0]
2. 常用方法(可变对象的'动作')
| 方法 | 作用 | 示例(假设 lst = [1, 2, 3]) |
|---|
append(x) | 末尾添加一个元素 | lst.append(4) → [1,2,3,4] |
extend(iterable) | 末尾添加多个元素 | lst.extend([4,5]) → [1,2,3,4,5] |
insert(i, x) | 在 i 位置插入 x | lst.insert(1, 99) → [1,99,2,3] |
remove(x) | 删除第一个值为 x 的元素 | lst.remove(2) → [1,3] |
pop([i]) | 删除并返回 i 位置元素(默认末尾) | lst.pop() → 3,列表变为 [1,2] |
clear() | 清空列表 | lst.clear() → [] |
index(x) | 返回第一个 x 的索引 | [1,2,3].index(2) → 1 |
count(x) | 统计 x 出现次数 | [1,2,2,3].count(2) → 2 |
sort() | 原地排序 | [3,1,2].sort() → [1,2,3] |
reverse() | 原地反转 | [1,2,3].reverse() → [3,2,1] |
copy() | 返回浅拷贝 | new_lst = lst.copy() |
⚠️ 注意:append 和 extend 的区别:
lst = [1, 2]
lst.append([3, 4])
lst.extend([5, 6])
3. 索引与切片(可读可写)
列表的切片不仅可读,还可赋值修改(这是可变性的体现)。
lst = [10, 20, 30, 40, 50]
print(lst[1:4])
lst[1:4] = [99, 100]
print(lst)
print([1, 2] + [3, 4])
print([0] * 5)
4. 列表的'坑':浅拷贝
列表的 copy() 或 [:] 是浅拷贝——只复制外层容器,内层元素还是引用。如果列表里包含可变对象(比如另一个列表),修改内层会影响拷贝。
a = [1, [2, 3]]
b = a.copy()
b[0] = 100
b[1][0] = 999
print(a)
四、字典:快速查找的'通讯录'
字典是可变映射,存储键值对,用花括号 {} 表示。键必须是不可变类型(如字符串、数字、元组),值可以是任意对象。
1. 创建字典
person = {"name": "Alice", "age": 25, "city": "New York"}
empty_dict = {}
dict_from_pairs = dict([("name", "Bob"), ("age", 30)])
dict_with_keywords = dict(name="Charlie", age=35)
squares_dict = {x: x**2 for x in range(5)}
2. 访问与修改
print(person["name"])
print(person.get("gender", "未知"))
person["age"] = 26
person["gender"] = "female"
person.update({"city": "Boston", "job": "engineer"})
3. 删除
del person["gender"]
age = person.pop("age")
last_item = person.popitem()
person.clear()
4. 视图:keys()、values()、items()
d = {"a": 1, "b": 2}
print(d.keys())
print(d.values())
print(d.items())
for k, v in d.items():
print(k, v)
5. 冷知识:字典从 Python 3.7 开始有序了!
以前字典是无序的,现在会保持插入顺序。但别依赖排序来做什么——想排序请用 sorted()。
6. 默认值:collections.defaultdict(选读)
如果想在访问不存在的键时自动生成默认值,可以用 defaultdict:
from collections import defaultdict
dd = defaultdict(int)
dd["count"] += 1
print(dd)
五、集合:去重与集合运算的高手
集合是可变无序集,元素必须唯一且不可变(所以不能放列表)。用花括号 {} 表示,但空集要用 set()。
1. 创建集合
s = {1, 2, 3}
empty_set = set()
from_list = set([1, 2, 2, 3])
squares_set = {x**2 for x in range(5)}
2. 修改集合
| 方法 | 作用 | 示例 |
|---|
add(x) | 添加元素 | s.add(4) |
remove(x) | 删除 x,不存在抛 KeyError | s.remove(2) |
discard(x) | 删除 x,不存在不报错 | s.discard(100) |
pop() | 随机删除并返回一个元素 | s.pop() |
clear() | 清空 | s.clear() |
3. 集合运算(数学课代表上线)
假设 a = {1, 2, 3},b = {2, 3, 4}
| 运算 | 符号 | 方法 | 结果 |
|---|
| 并集 | ` | ` | a.union(b) |
| 交集 | & | a.intersection(b) | {2, 3} |
| 差集 | - | a.difference(b) | {1} |
| 对称差 | ^ | a.symmetric_difference(b) | {1, 4} |
{1, 2}.issubset({1, 2, 3})
{1, 2, 3}.issuperset({1, 2})
4. 不可变版本:frozenset
如果你需要一个不能修改的集合(比如作为字典的键),可以用 frozenset:
fs = frozenset([1, 2, 3])
六、元组:不可变的'列表'
元组是不可变序列,用圆括号 () 表示。一旦创建,不能增删改元素。
1. 创建元组
t = (1, 2, 3)
single = (1,)
empty = ()
from_list = tuple([4, 5, 6])
2. 不可变?等等,有陷阱!
元组的不可变是指元素的引用不可变。如果元素本身是可变对象,那它的内容还是可以变的。
t = (1, [2, 3])
t[1].append(4)
3. 解包(元组最实用的特性)
point = (10, 20)
x, y = point
a, b, c = (1, 2, 3)
first, *rest = (1, 2, 3, 4)
4. 方法:只有两个
t = (1, 2, 2, 3)
print(t.count(2))
print(t.index(3))
5. 命名元组(选读)
collections.namedtuple 可以创建带字段名的元组,像轻量级对象:
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(10, 20)
print(p.x, p.y)
本章总结
| 数据结构 | 类型 | 可变? | 特点 | 常用场景 |
|---|
| 字符串 | 序列 | ❌ 不可变 | 文本处理 | 几乎所有程序 |
| 列表 | 序列 | ✅ 可变 | 万能容器,有序 | 存储任意序列 |
| 元组 | 序列 | ❌ 不可变 | 轻量,可哈希 | 固定数据,函数返回多值 |
| 字典 | 映射 | ✅ 可变 | 键值对,快速查找 | 结构化数据,缓存 |
| 集合 | 集合 | ✅ 可变 | 元素唯一,集合运算 | 去重,关系判断 |
- 列表用
[],元组用 (),字典用 {}(键值对),集合也用 {}(但元素单一)
- 可变对象的方法通常就地修改,不可变对象的方法返回新对象
- 能用元组就用元组(更安全、更轻量)
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- Gemini 图片去水印
基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
- curl 转代码
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online