4.1 列表(List)
列表是Python中最常用的数据结构,可以存储任意类型的数据。
4.1.1 列表创建
python
# 空列表
empty_list = []
empty_list2 = list()
# 包含元素的列表
numbers = [1, 2, 3, 4, 5]
fruits = ["apple", "banana", "cherry"]
# 混合类型
mixed = [1, "hello", 3.14, True, [1, 2, 3]]
# 使用list()函数
str_list = list("Python") # ['P', 'y', 't', 'h', 'o', 'n']
range_list = list(range(1, 6)) # [1, 2, 3, 4, 5]
print(numbers)
print(fruits)
print(mixed)
4.1.2 列表访问
python
fruits = ["apple", "banana", "cherry", "date", "elderberry"]
# 正向索引(从0开始)
print(fruits[0]) # apple
print(fruits[1]) # banana
print(fruits[4]) # elderberry
# 负向索引(从-1开始)
print(fruits[-1]) # elderberry(最后一个)
print(fruits[-2]) # date(倒数第二个)
# 索引越界会报错
# print(fruits[10]) # IndexError
# 获取列表长度
print(len(fruits)) # 5
4.1.3 列表切片
python
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# [start:end:step]
print(numbers[2:5]) # [2, 3, 4]
print(numbers[:5]) # [0, 1, 2, 3, 4](从开头到索引4)
print(numbers[5:]) # [5, 6, 7, 8, 9](从索引5到结尾)
print(numbers[:]) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9](完整复制)
print(numbers[::2]) # [0, 2, 4, 6, 8](步长为2)
print(numbers[1::2]) # [1, 3, 5, 7, 9](从索引1开始,步长为2)
print(numbers[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0](反转)
print(numbers[5:2:-1]) # [5, 4, 3](反向切片)
# 切片赋值
numbers[2:5] = [20, 30, 40]
print(numbers) # [0, 1, 20, 30, 40, 5, 6, 7, 8, 9]
4.1.4 列表方法
添加元素
python
fruits = ["apple", "banana"]
# append() - 末尾添加单个元素
fruits.append("cherry")
print(fruits) # ['apple', 'banana', 'cherry']
# insert() - 指定位置插入
fruits.insert(1, "blueberry")
print(fruits) # ['apple', 'blueberry', 'banana', 'cherry']
# extend() - 添加多个元素
fruits.extend(["date", "elderberry"])
print(fruits) # ['apple', 'blueberry', 'banana', 'cherry', 'date', 'elderberry']
# 使用 + 运算符
fruits = fruits + ["fig", "grape"]
print(fruits)
# 使用 += 运算符
fruits += ["kiwi"]
print(fruits)
删除元素
python
fruits = ["apple", "banana", "cherry", "date", "banana"]
# remove() - 删除指定值(第一个匹配项)
fruits.remove("banana")
print(fruits) # ['apple', 'cherry', 'date', 'banana']
# pop() - 删除指定索引(默认最后一个),并返回删除的元素
last = fruits.pop()
print(last) # banana
print(fruits) # ['apple', 'cherry', 'date']
second = fruits.pop(1)
print(second) # cherry
print(fruits) # ['apple', 'date']
# del - 删除指定索引或切片
del fruits[0]
print(fruits) # ['date']
fruits = ["apple", "banana", "cherry", "date", "elderberry"]
del fruits[1:3]
print(fruits) # ['apple', 'date', 'elderberry']
# clear() - 清空列表
fruits.clear()
print(fruits) # []
修改元素
python
fruits = ["apple", "banana", "cherry"]
# 修改单个元素
fruits[1] = "blueberry"
print(fruits) # ['apple', 'blueberry', 'cherry']
# 修改多个元素(切片赋值)
fruits[0:2] = ["avocado", "blackberry"]
print(fruits) # ['avocado', 'blackberry', 'cherry']
查找元素
python
fruits = ["apple", "banana", "cherry", "date", "banana"]
# index() - 查找元素索引(第一个匹配项)
index = fruits.index("banana")
print(index) # 1
# 指定查找范围
index = fruits.index("banana", 2) # 从索引2开始查找
print(index) # 4
# count() - 统计元素出现次数
count = fruits.count("banana")
print(count) # 2
# in 运算符 - 判断元素是否存在
print("apple" in fruits) # True
print("grape" in fruits) # False
print("grape" not in fruits) # True
排序
python
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
# sort() - 原地排序(修改原列表)
numbers.sort()
print(numbers) # [1, 1, 2, 3, 4, 5, 6, 9]
# 降序排序
numbers.sort(reverse=True)
print(numbers) # [9, 6, 5, 4, 3, 2, 1, 1]
# sorted() - 返回新列表(不修改原列表)
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
sorted_numbers = sorted(numbers)
print(numbers) # [3, 1, 4, 1, 5, 9, 2, 6](原列表不变)
print(sorted_numbers) # [1, 1, 2, 3, 4, 5, 6, 9]
# 字符串排序
fruits = ["banana", "apple", "cherry", "date"]
fruits.sort()
print(fruits) # ['apple', 'banana', 'cherry', 'date']
# 按长度排序
fruits.sort(key=len)
print(fruits) # ['date', 'apple', 'banana', 'cherry']
# reverse() - 反转列表
fruits.reverse()
print(fruits) # ['cherry', 'banana', 'apple', 'date']
复制列表
python
original = [1, 2, 3, 4, 5]
# 方法1: copy()
copy1 = original.copy()
# 方法2: 切片
copy2 = original[:]
# 方法3: list()
copy3 = list(original)
# 注意:直接赋值不是复制
not_copy = original # 只是引用,指向同一个列表
not_copy.append(6)
print(original) # [1, 2, 3, 4, 5, 6](原列表也改变了)
# 浅拷贝 vs 深拷贝
import copy
nested = [[1, 2], [3, 4]]
shallow = nested.copy() # 浅拷贝
deep = copy.deepcopy(nested) # 深拷贝
nested[0][0] = 99
print(nested) # [[99, 2], [3, 4]]
print(shallow) # [[99, 2], [3, 4]](浅拷贝,内层列表受影响)
print(deep) # [[1, 2], [3, 4]](深拷贝,完全独立)
4.1.5 列表推导式
python
# 基本语法
squares = [x ** 2 for x in range(1, 11)]
print(squares) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 带条件的列表推导式
evens = [x for x in range(1, 21) if x % 2 == 0]
print(evens) # [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
# 多重条件
numbers = [x for x in range(1, 101) if x % 2 == 0 if x % 5 == 0]
print(numbers) # [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
# if-else
numbers = [x if x % 2 == 0 else -x for x in range(1, 11)]
print(numbers) # [-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]
# 嵌套列表推导式
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]]
# 字符串处理
words = ["Hello", "World", "Python"]
upper_words = [word.upper() for word in words]
print(upper_words) # ['HELLO', 'WORLD', 'PYTHON']
# 多个循环
pairs = [(x, y) for x in range(1, 4) for y in range(1, 4)]
print(pairs) # [(1,1), (1,2), (1,3), (2,1), (2,2), (2,3), (3,1), (3,2), (3,3)]
4.1.6 多维列表
python
# 二维列表(矩阵)
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# 访问元素
print(matrix[0][0]) # 1
print(matrix[1][2]) # 6
print(matrix[2][1]) # 8
# 遍历二维列表
for row in matrix:
for num in row:
print(num, end=" ")
print()
# 创建二维列表
rows, cols = 3, 4
matrix = [[0 for _ in range(cols)] for _ in range(rows)]
print(matrix) # [[0,0,0,0], [0,0,0,0], [0,0,0,0]]
# 注意:不要这样创建(所有行共享同一个列表)
wrong_matrix = [[0] * cols] * rows # 错误!
wrong_matrix[0][0] = 1
print(wrong_matrix) # [[1,0,0,0], [1,0,0,0], [1,0,0,0]](所有行都变了)
4.2 元组(Tuple)
元组与列表类似,但元组是不可变的(immutable)。
4.2.1 元组创建
python
# 空元组
empty_tuple = ()
empty_tuple2 = tuple()
# 包含元素的元组
numbers = (1, 2, 3, 4, 5)
fruits = ("apple", "banana", "cherry")
# 单元素元组(注意逗号)
single = (1,) # 这是元组
not_tuple = (1) # 这是整数
print(type(single)) # <class 'tuple'>
print(type(not_tuple)) # <class 'int'>
# 省略括号
t = 1, 2, 3
print(type(t)) # <class 'tuple'>
# 使用tuple()函数
t = tuple([1, 2, 3])
t2 = tuple("Python") # ('P', 'y', 't', 'h', 'o', 'n')
4.2.2 元组操作
python
fruits = ("apple", "banana", "cherry")
# 索引
print(fruits[0]) # apple
print(fruits[-1]) # cherry
# 切片
print(fruits[0:2]) # ('apple', 'banana')
# 遍历
for fruit in fruits:
print(fruit)
# 拼接
t1 = (1, 2, 3)
t2 = (4, 5, 6)
t3 = t1 + t2
print(t3) # (1, 2, 3, 4, 5, 6)
# 重复
t = (1, 2) * 3
print(t) # (1, 2, 1, 2, 1, 2)
# 成员检查
print("apple" in fruits) # True
# 长度
print(len(fruits)) # 3
# count() - 统计元素出现次数
t = (1, 2, 3, 1, 1, 4)
print(t.count(1)) # 3
# index() - 查找元素索引
print(t.index(3)) # 2
4.2.3 元组的不可变性
python
t = (1, 2, 3)
# 不能修改元素
# t[0] = 10 # TypeError
# 不能添加元素
# t.append(4) # AttributeError
# 但元组中的可变元素可以修改
t = (1, [2, 3], 4)
t[1].append(5)
print(t) # (1, [2, 3, 5], 4)
# 可以重新赋值(创建新元组)
t = (1, 2, 3)
t = t + (4, 5)
print(t) # (1, 2, 3, 4, 5)
4.2.4 元组解包
python
# 基本解包
t = (1, 2, 3)
a, b, c = t
print(a, b, c) # 1 2 3
# 交换变量
x, y = 10, 20
x, y = y, x
print(x, y) # 20 10
# *运算符解包
first, *middle, last = (1, 2, 3, 4, 5)
print(first) # 1
print(middle) # [2, 3, 4]
print(last) # 5
# 函数返回多个值(实际返回元组)
def get_user_info():
return "Alice", 25, "Beijing"
name, age, city = get_user_info()
print(f"{name}, {age}, {city}")
# 忽略某些值
name, _, city = get_user_info() # 使用_忽略age
4.2.5 命名元组
python
from collections import namedtuple
# 创建命名元组类
Point = namedtuple('Point', ['x', 'y'])
# 创建实例
p = Point(10, 20)
# 访问字段
print(p.x) # 10
print(p.y) # 20
# 也可以像普通元组一样访问
print(p[0]) # 10
print(p[1]) # 20
# 更复杂的例子
Person = namedtuple('Person', ['name', 'age', 'city'])
alice = Person('Alice', 25, 'Beijing')
print(alice.name) # Alice
print(alice.age) # 25
print(alice.city) # Beijing
# 转换为字典
print(alice._asdict()) # {'name': 'Alice', 'age': 25, 'city': 'Beijing'}
4.2.6 元组 vs 列表
| 特性 | 列表 | 元组 |
|---|---|---|
| 可变性 | 可变 | 不可变 |
| 符号 | [] | () |
| 性能 | 较慢 | 较快 |
| 方法 | 多 | 少 |
| 使用场景 | 数据会改变 | 数据不变,如坐标、配置 |
python
# 何时使用元组
# 1. 函数返回多个值
def divmod_custom(a, b):
return a // b, a % b
# 2. 作为字典的键(列表不能作为键)
locations = {
(0, 0): "origin",
(1, 0): "right",
(0, 1): "up"
}
# 3. 保护数据不被修改
config = ("localhost", 8080, "admin")
4.3 字典(Dictionary)
字典是键值对的集合,使用键来访问值。
4.3.1 字典创建
python
# 空字典
empty_dict = {}
empty_dict2 = dict()
# 基本字典
person = {
"name": "Alice",
"age": 25,
"city": "Beijing"
}
# 使用dict()函数
person2 = dict(name="Bob", age=30, city="Shanghai")
# 从元组列表创建
pairs = [("a", 1), ("b", 2), ("c", 3)]
d = dict(pairs)
print(d) # {'a': 1, 'b': 2, 'c': 3}
# 使用zip创建
keys = ["name", "age", "city"]
values = ["Charlie", 35, "Guangzhou"]
person3 = dict(zip(keys, values))
print(person3)
# 字典推导式
squares = {x: x**2 for x in range(1, 6)}
print(squares) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
4.3.2 字典访问
python
person = {
"name": "Alice",
"age": 25,
"city": "Beijing"
}
# 使用键访问
print(person["name"]) # Alice
print(person["age"]) # 25
# 键不存在会报错
# print(person["email"]) # KeyError
# get()方法(安全访问)
print(person.get("name")) # Alice
print(person.get("email")) # None(不存在返回None)
print(person.get("email", "未设置")) # 未设置(指定默认值)
# 检查键是否存在
print("name" in person) # True
print("email" in person) # False
4.3.3 字典修改
python
person = {
"name": "Alice",
"age": 25
}
# 修改值
person["age"] = 26
print(person) # {'name': 'Alice', 'age': 26}
# 添加键值对
person["city"] = "Beijing"
print(person) # {'name': 'Alice', 'age': 26, 'city': 'Beijing'}
# update() - 批量更新
person.update({"age": 27, "email": "alice@example.com"})
print(person)
# setdefault() - 如果键不存在则设置
person.setdefault("country", "China")
print(person)
person.setdefault("name", "Bob") # name已存在,不会修改
print(person["name"]) # 仍然是Alice
4.3.4 字典删除
python
person = {
"name": "Alice",
"age": 25,
"city": "Beijing",
"email": "alice@example.com"
}
# del - 删除键值对
del person["email"]
print(person)
# pop() - 删除并返回值
age = person.pop("age")
print(age) # 25
print(person) # {'name': 'Alice', 'city': 'Beijing'}
# pop()指定默认值(键不存在时返回)
country = person.pop("country", "未知")
print(country) # 未知
# popitem() - 删除并返回最后一个键值对(Python 3.7+保证顺序)
item = person.popitem()
print(item) # ('city', 'Beijing')
print(person) # {'name': 'Alice'}
# clear() - 清空字典
person.clear()
print(person) # {}
4.3.5 字典遍历
python
person = {
"name": "Alice",
"age": 25,
"city": "Beijing"
}
# 遍历键
for key in person:
print(key)
for key in person.keys():
print(key)
# 遍历值
for value in person.values():
print(value)
# 遍历键值对
for key, value in person.items():
print(f"{key}: {value}")
# 字典推导式
squared = {x: x**2 for x in range(1, 6)}
print(squared)
# 筛选字典
person = {"name": "Alice", "age": 25, "city": "Beijing", "country": "China"}
filtered = {k: v for k, v in person.items() if len(str(v)) > 5}
print(filtered) # {'Beijing': 'Beijing', 'country': 'China'}
4.3.6 字典方法
python
person = {"name": "Alice", "age": 25}
# keys() - 获取所有键
keys = person.keys()
print(keys) # dict_keys(['name', 'age'])
print(list(keys)) # ['name', 'age']
# values() - 获取所有值
values = person.values()
print(list(values)) # ['Alice', 25]
# items() - 获取所有键值对
items = person.items()
print(list(items)) # [('name', 'Alice'), ('age', 25)]
# copy() - 复制字典(浅拷贝)
person_copy = person.copy()
# fromkeys() - 创建字典
keys = ["name", "age", "city"]
default_dict = dict.fromkeys(keys, "未知")
print(default_dict) # {'name': '未知', 'age': '未知', 'city': '未知'}
4.3.7 嵌套字典
python
# 字典嵌套
students = {
"s001": {
"name": "Alice",
"age": 20,
"scores": {"math": 95, "english": 88}
},
"s002": {
"name": "Bob",
"age": 21,
"scores": {"math": 87, "english": 92}
}
}
# 访问嵌套数据
print(students["s001"]["name"]) # Alice
print(students["s001"]["scores"]["math"]) # 95
# 遍历嵌套字典
for student_id, student_info in students.items():
print(f"学号:{student_id}")
print(f"姓名:{student_info['name']}")
print(f"数学成绩:{student_info['scores']['math']}")
print()
4.4 集合(Set)
集合是无序的、不重复的元素集合。
4.4.1 集合创建
python
# 创建集合
fruits = {"apple", "banana", "cherry"}
print(fruits)
# 空集合(注意不能用{})
empty_set = set() # 正确
# empty_set = {} # 这是空字典!
# 从列表创建(自动去重)
numbers = set([1, 2, 2, 3, 3, 3, 4])
print(numbers) # {1, 2, 3, 4}
# 从字符串创建
chars = set("hello")
print(chars) # {'h', 'e', 'l', 'o'}(自动去重)
# 集合推导式
squares = {x**2 for x in range(1, 6)}
print(squares) # {1, 4, 9, 16, 25}
4.4.2 集合操作
python
fruits = {"apple", "banana", "cherry"}
# 添加元素
fruits.add("date")
print(fruits)
# update() - 添加多个元素
fruits.update(["elderberry", "fig"])
print(fruits)
# 删除元素
fruits.remove("banana") # 不存在会报错
print(fruits)
fruits.discard("grape") # 不存在不会报错
print(fruits)
# pop() - 随机删除一个元素
item = fruits.pop()
print(f"删除了:{item}")
# clear() - 清空集合
fruits.clear()
print(fruits) # set()
# 成员检查
fruits = {"apple", "banana", "cherry"}
print("apple" in fruits) # True
print("grape" in fruits) # False
# 长度
print(len(fruits)) # 3
4.4.3 集合运算
python
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
# 并集(union) - 所有元素
print(set1 | set2) # {1, 2, 3, 4, 5, 6, 7, 8}
print(set1.union(set2))
# 交集(intersection) - 共同元素
print(set1 & set2) # {4, 5}
print(set1.intersection(set2))
# 差集(difference) - set1有但set2没有的
print(set1 - set2) # {1, 2, 3}
print(set1.difference(set2))
# 对称差集(symmetric_difference) - 不同时在两个集合中的元素
print(set1 ^ set2) # {1, 2, 3, 6, 7, 8}
print(set1.symmetric_difference(set2))
# 子集
set_a = {1, 2, 3}
set_b = {1, 2, 3, 4, 5}
print(set_a.issubset(set_b)) # True(a是b的子集)
print(set_b.issuperset(set_a)) # True(b是a的超集)
# 是否有交集
set_c = {6, 7, 8}
print(set_a.isdisjoint(set_c)) # True(没有交集)
4.4.4 frozenset(不可变集合)
python
# 创建不可变集合
fs = frozenset([1, 2, 3, 4, 5])
# 不能添加删除元素
# fs.add(6) # AttributeError
# 可以作为字典的键或集合的元素
d = {fs: "frozen"}
s = {fs, frozenset([6, 7])}
print(d)
print(s)
# 支持集合运算
fs1 = frozenset([1, 2, 3])
fs2 = frozenset([3, 4, 5])
print(fs1 | fs2) # frozenset({1, 2, 3, 4, 5})
4.5 数据结构选择指南
| 需求 | 使用 |
|---|---|
| 有序、可重复、可修改 | 列表(list) |
| 有序、可重复、不可修改 | 元组(tuple) |
| 键值对映射 | 字典(dict) |
| 无序、不重复、可修改 | 集合(set) |
| 无序、不重复、不可修改 | frozenset |
python
# 示例场景
# 购物车(可修改、有顺序)
shopping_cart = ["apple", "banana", "apple"] # 列表
# 坐标点(不变)
point = (10, 20) # 元组
# 学生信息(键值对)
student = {"name": "Alice", "age": 20} # 字典
# 去重(不重复)
unique_numbers = {1, 2, 3, 2, 1} # 集合,结果{1, 2, 3}
4.6 参考资料
官方文档
- 数据结构:https://docs.python.org/zh-cn/3/tutorial/datastructures.html
- 列表方法:https://docs.python.org/zh-cn/3/tutorial/datastructures.html#more-on-lists
- 字典方法:https://docs.python.org/zh-cn/3/library/stdtypes.html#mapping-types-dict