Skip to content

08|元组与范围

元组和列表类似,但创建后不能修改。这个限制让元组在某些场景下比列表更合适——作为字典的键、函数返回的多个值、配置项等不需要修改的数据。

range 则是一个专门生成整数序列的对象,常用于循环计数。

一、元组

创建元组

python
coords = (10, 20)
single = (42,)     # 单元素元组必须有逗号,(42) 会被解析为括号表达式
empty = ()

元组可以省略括号:

python
coords = 10, 20    # 等价于 (10, 20)

但省略括号容易和函数参数混淆,建议显式写括号。

不可变性

元组创建后不能增删改元素:

python
t = (1, 2, 3)
t[0] = 10     # TypeError: 'tuple' object does not support item assignment
t.append(4)   # AttributeError: 'tuple' object has no attribute 'append'

但如果元组内部包含可变对象(如列表),那个可变对象本身仍然可以修改:

python
t = (1, [2, 3])
t[1].append(4)    # 可以,修改的是列表,不是元组
print(t)          # (1, [2, 3, 4])

元组的不可变指的是"元组这个容器的结构不变"——元素的引用不变。引用指向的对象如果是可变的,对象内部仍然可以变化。

索引和切片

元组的索引、切片操作与列表完全相同:

python
t = ("a", "b", "c", "d")
t[0]       # 'a'
t[-1]      # 'd'
t[1:3]     # ('b', 'c')
t[::-1]    # ('d', 'c', 'b', 'a')

解包

元组最实用的特性是解包——把一个序列拆开赋给多个变量:

python
x, y = (10, 20)
# x = 10, y = 20

# 交换两个变量
a, b = 1, 2
a, b = b, a
# a = 2, b = 1

* 接收剩余元素:

python
first, *rest = (1, 2, 3, 4)
# first = 1, rest = [2, 3, 4]

first, *middle, last = (1, 2, 3, 4)
# first = 1, middle = [2, 3], last = 4

*rest 接收到的始终是列表,即使原序列是元组。

元组作为字典键

元组是不可变的,可以作为字典的键;列表是可变的,不能作为键:

python
cache = {}
cache[("user", 1)] = "Alice"    # 可以
cache[["user", 1]] = "Alice"    # TypeError: unhashable type: 'list'

与列表的选择

特性列表元组
可变
性能稍慢稍快
能否作为字典键
语义"一组会变化的数据""一组固定的记录"

不确定时用列表。明确数据不会变、或需要作为字典键时,用元组。

二、range

range 生成整数序列,常用于循环计数。

python
# range(stop):从 0 开始到 stop-1
range(5)        # 0, 1, 2, 3, 4

# range(start, stop):从 start 开始到 stop-1
range(1, 6)     # 1, 2, 3, 4, 5

# range(start, stop, step):指定步长
range(0, 10, 2)   # 0, 2, 4, 6, 8
range(10, 0, -1)  # 10, 9, 8, ..., 1

range 不是列表,而是一个"惰性"对象——它只在需要时计算下一个值:

python
r = range(5)
type(r)         # <class 'range'>
list(r)         # [0, 1, 2, 3, 4],转成列表才能看到全部内容

惰性意味着占用内存少。range(1_000_000) 不会占用一百万个整数的内存,只在迭代时逐个生成。

range 支持索引和 in 判断:

python
r = range(0, 10, 2)
r[3]        # 6
4 in r      # True
5 in r      # False

记忆锚点:元组不可变,单元素必须有逗号 (42,);元组解包是核心特性,*rest 接收剩余元素;元组可作为字典键,列表不能;range 是惰性对象,不占大量内存;range(5) 生成 0-4,range(1, 6) 生成 1-5。