range 函数详解
基本功能
range()
用于生成一个不可变的整数序列,常用于 for
循环中控制迭代次数。
它不直接返回列表,而是返回一个 range
对象(可迭代、惰性计算)。
语法
1 2 3
| range(stop) range(start, stop) range(start, stop, step)
|
参数 |
含义 |
start |
起始值(包含),默认为 0 |
stop |
结束值(不包含) |
step |
步长,默认为 1 |
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| for i in range(5): print(i)
for i in range(2, 6): print(i)
for i in range(0, 10, 2): print(i)
for i in range(5, 0, -1): print(i)
|
range 对象的特性
- 内存高效:不是一次性生成所有数字,而是“惰性计算”,只在需要时生成下一个值。
- 可迭代但不可变:不能修改元素,也不能赋值。
- 支持索引和切片(Python 3.2+):
1 2 3
| r = range(2, 10, 2) print(r[1]) print(r[:2])
|
1
| 1000 in range(0, 10000, 2)
|
转换为列表或元组
如果需要立即得到所有值:
1 2
| list(range(5)) tuple(range(2, 8))
|
注意:range
本身不是列表,使用 list()
才会真正生成数据。
常见用途
场景 |
示例 |
控制循环次数 |
for i in range(10): |
遍历索引 |
for i in range(len(lst)): |
生成等差数列 |
range(0, 100, 5) |
反向遍历 |
range(len(lst)-1, -1, -1) |
常见误区
错误:认为 range
返回列表(实际是对象)
正确:range(5)
是 <class 'range'>
类型
错误:试图修改 range
元素
range
是不可变的
错误:用 range(len(...))
遍历元素(应优先用 for item in lst
)
推荐:只有需要索引时才用 range(len(lst))
,否则用直接遍历
enumerate 函数详解
基本功能
enumerate()
用于在遍历可迭代对象时,同时获取索引和元素值,避免手动维护计数器。
语法
1
| enumerate(iterable, start=0)
|
参数 |
含义 |
iterable |
任意可迭代对象(列表、字符串、元组等) |
start |
起始索引,默认为 0 |
使用示例
1 2 3 4 5 6 7 8
| lst = ['a', 'b', 'c']
for i, value in enumerate(lst): print(i, value)
|
自定义起始索引
1 2 3 4 5 6
| for i, value in enumerate(lst, start=1): print(i, value)
|
遍历字符串
1 2 3 4 5
| for i, ch in enumerate("hello"): print(i, ch)
|
enumerate 返回什么
enumerate()
返回一个枚举对象(iterator),每次迭代返回一个 (index, value)
元组。
你可以将其转为列表查看内容:
1
| list(enumerate(['x', 'y']))
|
底层原理
enumerate
等价于以下生成器函数:
1 2 3 4 5
| def my_enumerate(iterable, start=0): count = start for item in iterable: yield count, item count += 1
|
所以它是惰性计算的,内存友好。
实际应用场景
场景 1:需要索引和值
1 2
| for idx, name in enumerate(names): print(f"{idx+1}. {name}")
|
场景 2:查找满足条件的索引
1 2 3 4
| for i, x in enumerate(nums): if x == target: print(f"Found at index {i}") break
|
场景 3:与 zip 结合处理多个列表
1 2
| for i, (a, b) in enumerate(zip(list1, list2)): print(f"{i}: {a} vs {b}")
|
常见误区
错误:认为 enumerate
是从 1 开始的
默认从 0 开始,可用 start=
修改
错误:只用于列表
可用于任何可迭代对象:字符串、元组、字典键、生成器等
错误:在循环中修改 i
能跳过元素
i
是局部变量,修改不影响循环流程
对比:range 与 enumerate
特性 |
range(len(lst)) |
enumerate(lst) |
是否需要索引 |
是 |
是 |
是否需要元素值 |
需要 lst[i] |
直接获取 |
代码可读性 |
一般 |
更好 |
性能 |
略快(纯整数) |
稍慢(生成元组) |
内存 |
惰性 |
惰性 |
推荐程度 |
不推荐用于遍历元素 |
强烈推荐 |
推荐写法对比
1 2 3 4 5 6 7
| for i in range(len(lst)): print(i, lst[i])
for i, value in enumerate(lst): print(i, value)
|
高级技巧与组合用法
enumerate 与 range 组合使用
如果你想从某个索引开始遍历一段序列:
1 2 3 4 5 6 7 8 9 10
| lst = ['a', 'b', 'c', 'd', 'e'] start_idx = 2 end_idx = 5
for i, value in enumerate(lst[start_idx:end_idx], start=start_idx): print(i, value)
|
这样索引是原始位置,不是切片后的 0,1,2。
enumerate 配合条件跳过
1 2 3 4
| for i, char in enumerate(s): if char == ' ': continue print(i, char)
|
获取 enumerate 的长度
enumerate
是迭代器,不支持 len()
:
1 2 3 4 5
| e = enumerate([1,2,3])
len(list(enumerate([1,2,3])))
|
1 2 3 4 5
| from itertools import islice
for i, x in islice(enumerate(large_iterable), 5): print(i, x)
|
性能对比(小数据无差别)
方法 |
适用场景 |
性能 |
for x in lst |
只需要值 |
最快 |
for i, x in enumerate(lst) |
需要索引+值 |
推荐 |
for i in range(len(lst)) |
需要索引+值 |
可用但不优雅 |
for i in range(n) |
固定次数循环 |
必用 |
对于小数据,性能差异可忽略;对于大循环,enumerate
更安全、可读性更高。
总结:最佳实践
问题 |
推荐做法 |
遍历列表并需要索引 |
for i, x in enumerate(lst) |
只需要元素 |
for x in lst |
固定次数循环 |
for i in range(n) |
反向遍历索引 |
for i in range(len(lst)-1, -1, -1) |
从某索引开始枚举 |
enumerate(lst[start:], start=start) |
提取带索引的数据 |
list(enumerate(…)) |
一句话口诀记忆
range
造数字,enumerate
配对出(索引, 元素)