列表是 Python 中最常用的可变 (Mutable) 序列类型。
基本操作与构造
- 表示: 使用方括号
[], 元素间用逗号分隔。 - 构造函数:
list(iterable)。可将元组、字符串、range 等转换为列表。 - 运算:
- 加法 (+):
[1, 2] + [3][1, 2, 3](连接,产生新列表)。 - 乘法 (*):
[1] * 3[1, 1, 1](重复,产生新列表)。
- 加法 (+):
- 成员判定:
x in lst(时间复杂度 O(n))。
索引与切片 (Indexing & Slicing)
1. 访问 (Access)
- Index:
a[i]。支持负数索引(-1 为最后一个)。 - Slice:
a[start:stop:step]。 缺省值:start默认为0,stop默认为长度,step默认为1。 常用技巧:a[::-1](反转列表),a[:](浅拷贝整个列表)。
2. 修改 (Modification)
列表是可变的,支持原位修改。
lst = [0, 1, 2, 3, 4]
# 索引修改 (必须存在)
lst[0] = 99 # -> [99, 1, 2, 3, 4]
# 切片修改 (功能强大:可替换、插入、删除)
# 将索引 1 到 3 的片段替换为新的列表
lst[1:3] = ['a', 'b', 'c']
# 结果: [99, 'a', 'b', 'c', 3, 4] (长度可以改变)
# 即使是切片赋值,右侧也必须是 Iterable
lst[1:2] = [100] # 正确
# lst[1:2] = 100 # 报错!TypeError
常用方法 (Methods) 与删除
| 方法/操作 | 说明 |
|---|---|
.append(x) | 在末尾添加元素 x。 |
.extend(iterable) | 将 iterable 中的所有元素追加到末尾。 |
.insert(i, x) | 在索引 i 处插入 x。 |
.remove(x) | 删除第一个值为 x 的元素。如果不存在则报错。 |
.pop([i]) | 删除并返回索引 i 处的元素(默认最后一个)。 |
.clear() | 清空列表,变为 []。 |
.index(x) | 返回第一个 x 的索引。 |
.count(x) | 统计 x 出现的次数。 |
.sort(key=.., reverse=..) | 就地排序 (In-place),无返回值 (None)。 |
.reverse() | 就地反转,无返回值。 |
del lst[i] | 删除指定索引的元素。 |
del lst[start:stop] | 删除切片范围内的元素。 |
列表推导式 (List Comprehension)
一种简洁构建列表的方法,通常比 for 循环更快。
- 基础语法:
[expression for item in iterable if condition] - 嵌套 (Nested): 对应嵌套的 for 循环。
# 目标: 展平二维数组 matrix = [[1, 2], [3, 4]]
flat = [num for row in matrix for num in row]
# 等价于:
# for row in matrix:
# for num in row: ...
核心难点:拷贝机制 (Shallow vs Deep Copy)
这是列表最容易出错的地方,必须严格区分三种拷贝层级。
1. 引用赋值 (Reference)
b = a。不创建新对象,a 和 b 指向同一块内存。
2. 浅拷贝 (Shallow Copy)
创建一个新列表容器,但列表里面的元素依然是原对象的引用。 触发方式:
b = a[:](切片)b = a.copy()b = list(a)
a = [[1], [2]] # 嵌套列表
b = a.copy() # 浅拷贝
b[0].append(9) # 修改内部对象
print(a) # [[1, 9], [2]] -> 原列表 a 也变了!
# 因为 b[0] 和 a[0] 指向的是同一个小列表对象
3. 深拷贝 (Deep Copy)
递归地拷贝列表及其包含的所有子对象。需导入 copy 模块。
import copy
c = copy.deepcopy(a) # 完全独立,修改 c 不会影响 a
4. 乘法操作符 * 的陷阱
lst * n 执行的是浅拷贝。
Warning — 千万别这样初始化二维数组!
错误写法:
# 创建一个 3x3 矩阵 matrix = [[0] * 3] * 3 # 结果: [[0,0,0], [0,0,0], [0,0,0]] # 问题: 这3个内部列表其实是同一个对象的引用! matrix[0][0] = 99 print(matrix) # 结果: [[99,0,0], [99,0,0], [99,0,0]] -> 3行全变了正确写法 (List Comprehension):
# 推导式每次循环都会重新计算表达式 -> 创建新的列表对象 matrix = [[0] * 3 for _ in range(3)]
Note — List Comprehension 的求值特性
推导式中的表达式(expression)在每次迭代时都会重新求值 (Re-evaluates)。
[[1] for _ in range(3)]: 循环3次,每次都创建一个新的[1]。相当于对[1]做了 Deep Copy 的效果(虽然技术上不是通过 deepcopy 实现的)。
元组可以被视为不可变的列表 (Immutable List)。一旦创建,其长度和内部元素的指向都不能改变。
表示与构造
- 符号: 使用圆括号
()。 - 构造函数:
tuple(iterable)。 - 空元组:
t = ()。
Warning — 单元素元组的陷阱
创建只有一个元素的元组时,必须在元素后加逗号,否则 Python 会将其识别为普通的数学运算括号(即该元素本身的类型)。
t1 = (1) # <class 'int'> (整数 1) t2 = (1,) # <class 'tuple'> (元组)
基本操作
元组支持大部分列表的只读操作:
- 索引 (Indexing):
t[0],t[-1]。 - 切片 (Slicing):
t[1:3]。返回一个新的元组。 - 成员判定:
x in t。 - 运算:
- 加法:
(1, 2) + (3,)(1, 2, 3)(创建新元组)。 - 乘法:
(1,) * 3(1, 1, 1)。
- 加法:
常用方法
由于不可变,元组没有 append, extend, remove 等修改方法。仅支持查询:
.count(x): 统计 x 出现的次数。.index(x): 返回 x 第一次出现的索引。
没有“元组推导式”
Note — Tuple Comprehension 不存在
在 Python 中,使用圆括号包裹的推导式语法
(x for x in ...)并不是元组推导式,而是创建一个生成器对象 (Generator Expression)。如果需要通过推导逻辑创建元组,必须显式调用
tuple():# 错误理解:以为这是元组 g = (i * 2 for i in range(3)) print(type(g)) # <class 'generator'> # 正确创建元组 t = tuple(i * 2 for i in range(3)) print(t) # (0, 2, 4)
进阶:元组真的”不可变”吗?
元组的不可变性指的是**“其存储的引用(内存地址)不可变”**。如果元组内部包含可变对象(如列表),该内部对象的内容是可以修改的。
t = (1, [2, 3])
# t[0] = 2 # 报错!TypeError (不能修改引用)
# t[1] = [4] # 报错!TypeError (不能修改引用)
t[1].append(4) # 合法!修改了内部列表的内容
print(t) # (1, [2, 3, 4])
Practice examples
#####list_lasted
#list_comprehention
print([x**2 for x in range(1,11) if x%2 == 0])
print([x**2 for x in range(1,11)])
#nested_comprehension
matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
print([[row[i] for row in matrix] for i in range(4)])
#built-in function
list_test = [2,1,3,4]
#-len
print(len(list_test))
#-min/max
print(min(list_test),max(list_test))
#-sum
print(sum(list_test))
#-sorted
print(sorted(list_test))
#-reversed
print(list(reversed(list_test)))
print("".join(str(x)for x in list_test),end="")
#emurate
lst = [1,2,3,4]
for i,_ in enumerate(lst):
print(i,_)
#####dictionary
#merge: the last one will cover the first one if they shared the same keywords.
a = {1:0,2:1,3:2,4:3}
b = {1:1,2:1,3:2}
c = {**a,**b}
print(c)
#loop through dictionaries
dictionary = {1:0,2:1,3:2,4:3}
for x in dictionary:
print(x)
for x in dictionary:
print(dictionary[x])
for x in dictionary.values():
print(x)
for x,y in dictionary.items():
print(x,y)
#upper函数不会自动修改,而是返回修改值
#lst.sort不会返回修改值,而是自动修改