第04章 数据结构

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 参考资料

官方文档

学习资源

相关推荐
启扶农19 小时前
lecen:一个更好的开源可视化系统搭建项目--页面、模板、元组--全低代码|所见即所得|利用可视化设计器构建你的应用系统-做一个懂你的人
低代码·模板·元组·表单设计器·页面·页面可视化·页面设计器
2401_841495644 天前
【Python高级编程】Python中常见的运算符、函数与方法总结
字符串·集合·文件·列表·元组·字典·运算符
2401_841495644 天前
【Python高级编程】Python 核心语法速查演示
python·字符串·集合·列表·元组·字典·运算符
alwaysrun2 个月前
Rust中元组详解
rust·元组·tuple·解构
Jasmine_llq7 个月前
《CF912E Prime Gift》
算法·优先队列(最小堆)·集合去重
程序员张小厨10 个月前
【0014】Python数据类型-元组类型详解
python·元组·python推导式·python元组·python元组数据类型·元组数据类型·python元组遍历
殇淋狱陌1 年前
第四章 列表(List)&元组(Tuple)以及代码格式基础语法及操作
数据结构·python·数据分析·list·元组
云边的快乐猫1 年前
python中的列表、元组、字典的介绍与使用
开发语言·python·列表·元组·字典
KevinRay_1 年前
【Python入门】Python数据类型
python·面向对象·列表·元组·二维列表