Python 中列表(List)和元组(Tuple)的区别?
Python 中的 列表(List) 和 元组(Tuple) 都是用于存储有序数据集合的序列,但它们之间有几个关键的区别。
最核心的区别在于:列表是可变的(Mutable),而元组是不可变的(Immutable)。
以下是详细的对比分析:
1. 可变性 (Mutability)
- 列表 (List): 是可变的。这意味着创建列表后,你可以随意修改、添加或删除其中的元素。
- 元组 (Tuple): 是不可变的。一旦创建,就不能修改其内容(不能增加、删除或更改元素)。
python
# 列表
my_list = [1, 2, 3]
my_list[0] = 100 # 合法,列表变为 [100, 2, 3]
# 元组
my_tuple = (1, 2, 3)
# my_tuple[0] = 100 # 报错!TypeError: 'tuple' object does not support item assignment
2. 语法 (Syntax)
- 列表: 使用方括号
[]定义。 - 元组: 使用圆括号
()定义。- 注意: 定义只有一个元素的元组时,必须加逗号,例如
(1,),否则 Python 会将其视为普通的括号运算。
- 注意: 定义只有一个元素的元组时,必须加逗号,例如
python
lst = [1, 2, 3]
tup = (1, 2, 3)
single_tup = (1,)
not_a_tup = (1) # 这是整数 1
3. 性能与内存 (Performance & Memory)
- 元组: 由于是不可变的,Python 可以在内部对其进行优化。元组通常比列表占用更少的内存,且创建和遍历的速度稍微快一些。
- 列表: 为了支持动态扩容(添加元素),列表需要分配额外的内存空间(Overhead),因此占用内存较大。
python
import sys
a_list = [1, 2, 3, 4, 5]
a_tuple = (1, 2, 3, 4, 5)
print(sys.getsizeof(a_list)) # 结果通常较大 (例如 104 bytes)
print(sys.getsizeof(a_tuple)) # 结果通常较小 (例如 80 bytes)
4. 方法支持 (Methods)
- 列表: 拥有丰富的方法,如
append(),extend(),insert(),remove(),pop(),sort(),reverse()等。 - 元组: 支持的方法很少,主要是
count()(统计元素出现次数) 和index()(查找元素索引)。
5. 作为字典的键 (Dictionary Keys)
- 元组: 因为是不可变的(且如果其内部元素也是不可变的),它是可哈希的(Hashable),所以可以作为字典的 Key,也可以放入集合(Set)中。
- 列表: 因为是可变的,它是不可哈希的(Unhashable),所以不能作为字典的 Key。
python
my_dict = {}
my_tuple = (1, 2)
my_list = [1, 2]
my_dict[my_tuple] = "合法"
# my_dict[my_list] = "报错" # TypeError: unhashable type: 'list'
6. 使用场景 (Use Cases)
虽然两者都能存数据,但在 Python 惯例中:
- 列表: 通常用于存储同构数据(即相同类型的数据),且数据长度可能会发生变化。类似于数据库中的“一列”数据。
- 元组: 通常用于存储异构数据(不同类型的数据),表示一个特定的结构或记录。类似于数据库中的“一行”记录(例如:
(姓名, 年龄, 性别))。
总结对比表
| 特性 | 列表 (List) | 元组 (Tuple) |
|---|---|---|
| 可变性 | 可变 (Mutable) | 不可变 (Immutable) |
| 语法 | [1, 2, 3] |
(1, 2, 3) |
| 速度/性能 | 稍慢 | 稍快 |
| 内存占用 | 较大 | 较小 |
| 方法数量 | 多 (append, remove...) | 少 (count, index) |
| 作字典Key | 不可以 | 可以 |
| 语义 | 变长序列,同类数据 | 定长记录,结构化数据 |
一个特殊的陷阱
虽然元组本身是不可变的,但如果元组中包含了一个可变对象(如列表),那么这个内部的列表是可以被修改的。
python
t = (1, 2, [3, 4])
# t[0] = 5 # 报错:不能修改元组的引用
t[2][0] = 99 # 合法!因为 t[2] 指向的是一个列表,列表内部是可变的
print(t) # 输出: (1, 2, [99, 4])
右滑查看面试常问