Python基础指南之range()函数的参数详解与高效用法
一、开篇:for循环的灵魂伴侣
在Python中,range()函数几乎和for循环形影不离。每当你需要"重复N次"或"遍历一段数字"时,就会用到它:
for i in range(10):
print(i) # 0到9
for i in range(5, 10):
print(i) # 5到9
for i in range(0, 10, 2):
print(i) # 0, 2, 4, 6, 8
看起来简单,但range()有一些不太广为人知的细节:它是惰性计算的、它支持负数步长、它可以用in做O(1)的成员检查、它甚至可以和len()配合使用。
更重要的,很多Python初学者滥用range(len(...)),而错过了更Pythonic的迭代方式。今天就来彻底掌握range()。
全文将围绕三个核心问题展开:range()的参数到底怎么用、它为什么高效、什么时候该用什么时候不该用。
二、range()的三种参数形式
2.1 单参数:range(stop)
# range(stop) —— 从0到stop-1
# 等价于数学中的 [0, stop)
for i in range(5):
print(i, end=' ')
# 输出: 0 1 2 3 4
# 转换为列表查看内容
print(list(range(5))) # [0, 1, 2, 3, 4]
print(list(range(1))) # [0]
print(list(range(0))) # [] —— stop=0 生成空range
# print(list(range(-5))) # [] —— 负数也一样是空的
# 📝 记忆技巧:range(n) 产生 n 个数字(从0到n-1)
2.2 双参数:range(start, stop)
# range(start, stop) —— 从start到stop-1
# 等价于数学中的 [start, stop)
for i in range(5, 10):
print(i, end=' ')
# 输出: 5 6 7 8 9
print(list(range(3, 8))) # [3, 4, 5, 6, 7]
print(list(range(-3, 3))) # [-3, -2, -1, 0, 1, 2]
print(list(range(10, 5))) # [] —— start > stop,空range
# 计算range中的元素个数:stop - start(当start < stop时)
print(len(range(5, 10))) # 5
print(len(range(-3, 3))) # 6
2.3 三参数:range(start, stop, step)
# range(start, stop, step) —— 从start开始,每次加step,直到达到或超过stop # 正步长 print(list(range(0, 10, 2))) # [0, 2, 4, 6, 8] —— 偶数 print(list(range(1, 10, 2))) # [1, 3, 5, 7, 9] —— 奇数 print(list(range(0, 100, 10))) # [0, 10, 20, 30, ..., 90] # 负步长(倒序) print(list(range(10, 0, -1))) # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] print(list(range(10, 0, -2))) # [10, 8, 6, 4, 2] print(list(range(5, -5, -1))) # [5, 4, 3, 2, 1, 0, -1, -2, -3, -4] # ⚠️ step不能为0! # list(range(0, 10, 0)) # ValueError: range() arg 3 must not be zero # 步长的符号决定方向 # step > 0: 从start向stop增长,要求 start < stop 才有元素 # step < 0: 从start向stop减小,要求 start > stop 才有元素 print(list(range(0, 10, 2))) # 有元素: start(0) < stop(10), step(2) > 0 print(list(range(10, 0, 2))) # 空!start(10) > stop(0) 但 step(2) > 0 print(list(range(10, 0, -2))) # 有元素: start(10) > stop(0), step(-2) < 0
2.4 参数名称
# range的参数也可以使用关键字 r1 = range(stop=5) r2 = range(start=2, stop=8) r3 = range(start=10, stop=0, step=-2) # 但不常用的组合可能无法使用关键字 # range(start=0, 10) # SyntaxError!位置参数不能在关键字参数后面 # 📝 建议:大多数情况下使用位置参数更简洁 # range(5) 而不是 range(stop=5) # range(2, 8) 而不是 range(start=2, stop=8)
三、range对象的高效特性
3.1 惰性计算(Lazy Evaluation)
# range() 不创建包含所有元素的列表
# 它是一个"序列对象",按需生成值
import sys
# range对象非常小!
r = range(1000000) # 一百万个元素
lst = list(range(1000000)) # 一百万个元素的列表
print(f"range对象大小: {sys.getsizeof(r):,} bytes") # 约48 bytes
print(f"列表对象大小: {sys.getsizeof(lst):,} bytes") # 约8,000,000 bytes
# range只在迭代时计算下一个值,不存储所有值
# 这是它比列表高效得多的原因
# range对象的重要特性
r = range(10)
print(len(r)) # 10 —— O(1)计算
print(r[0]) # 0 —— 通过公式计算
print(r[5]) # 5
print(r[-1]) # 9 —— 支持负索引
# print(r[100]) # IndexError
3.2 O(1)的成员检查
# range的 in 操作是O(1)的!
# 它通过数学公式检查,而不是遍历所有元素
r = range(0, 1000000, 2)
print(500000 in r) # True(O(1)时间!)
print(500001 in r) # False(O(1)时间!)
# 对比列表的O(n)检查
import timeit
lst = list(r)
t_range = timeit.timeit(lambda: 999998 in r, number=10000)
t_list = timeit.timeit(lambda: 999998 in lst, number=10000)
print(f"range in: {t_range:.4f}s") # 极快
print(f"list in: {t_list:.4f}s") # 慢得多
# range的in检查原理
def explain_range_contains(r, x):
"""解释range如何做成员检查"""
start, stop, step = r.start, r.stop, r.step
if step > 0:
in_range = start <= x < stop
if in_range:
# 检查x是否落在step的倍数上
return (x - start) % step == 0
else:
in_range = stop < x <= start
if in_range:
return (x - start) % step == 0
return False
3.3 支持索引和切片
r = range(0, 100, 3) # 0, 3, 6, ..., 99 # 索引——O(1)计算 print(r[0]) # 0 print(r[1]) # 3 print(r[10]) # 30 print(r[-1]) # 99 —— 最后一个 # 切片——返回新的range对象(也是O(1)!) print(r[5:15]) # range(15, 45, 3) print(r[:5]) # range(0, 15, 3) print(r[::2]) # range(0, 100, 6) —— 步长加倍 # 验证切片结果 print(list(r[5:15])) # [15, 18, 21, 24, 27, 30, 33, 36, 39, 42] print(list(r[:5])) # [0, 3, 6, 9, 12] print(list(r[::2])) # [0, 6, 12, 18, ...] # 支持 reversed() print(list(reversed(r))[:5]) # [99, 96, 93, 90, 87] # 支持 == != 比较 r1 = range(0, 10, 2) r2 = range(0, 10, 2) r3 = range(0, 9, 2) print(r1 == r2) # True —— 相同参数 print(r1 == r3) # False
四、range()的实用技巧
4.1 常用模式
# 模式1:重复N次
for _ in range(10):
print("Hello") # 打印10次
# 模式2:生成N个元素的列表
squares = [i**2 for i in range(1, 11)]
print(squares) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 模式3:倒序(两种方式)
# 方式A:使用reversed()
for i in reversed(range(10)):
print(i, end=' ') # 9 8 7 6 5 4 3 2 1 0
# 方式B:使用负步长
for i in range(9, -1, -1):
print(i, end=' ') # 9 8 7 6 5 4 3 2 1 0
# 模式4:跳过
for i in range(0, 100, 10):
print(i, end=' ') # 0 10 20 30 40 50 60 70 80 90
# 模式5:并行遍历多个列表(避免range(len()))
names = ["张三", "李四", "王五"]
scores = [85, 92, 78]
# ❌ 不推荐
for i in range(len(names)):
print(f"{names[i]}: {scores[i]}")
# ✅ 推荐
for name, score in zip(names, scores):
print(f"{name}: {score}")
4.2 range()的数学应用
# 生成等差数列
def arithmetic_sequence(start, end, step):
"""生成等差数列"""
return list(range(start, end + (1 if step > 0 else -1), step))
print(arithmetic_sequence(1, 10, 2)) # [1, 3, 5, 7, 9]
print(arithmetic_sequence(10, 1, -3)) # [10, 7, 4, 1]
# 生成乘法表
for i in range(1, 10):
for j in range(1, i + 1):
print(f"{j}×{i}={i*j}", end='\t')
print()
# 斐波那契数列(利用range的迭代次数控制)
def fibonacci(n):
"""生成前n个斐波那契数"""
result = []
a, b = 0, 1
for _ in range(n):
result.append(a)
a, b = b, a + b
return result
print(fibonacci(10)) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
# 分页数据生成
def paginate(items, page_size):
"""将数据分页"""
pages = []
for i in range(0, len(items), page_size):
pages.append(items[i:i + page_size])
return pages
data = list(range(25))
pages = paginate(data, 10)
for i, page in enumerate(pages, 1):
print(f"第{i}页: {page}")
4.3 range()与列表索引的高级配合
# 当你确实需要索引时,range(len())是可以的
# 但通常在特定的场景下
# 场景1:修改原列表的元素
numbers = [1, 2, 3, 4, 5]
for i in range(len(numbers)):
numbers[i] = numbers[i] ** 2
print(numbers) # [1, 4, 9, 16, 25]
# 场景2:操作相邻元素
data = [3, 1, 4, 1, 5, 9, 2, 6]
for i in range(len(data) - 1):
if data[i] > data[i + 1]:
print(f"下降: {data[i]} → {data[i+1]} at index {i}")
# 场景3:从后往前处理
stack = ['a', 'b', 'c', 'd', 'e']
for i in range(len(stack) - 1, -1, -1):
print(f"弹出: {stack[i]}")
# 场景4:跳跃处理
data = list(range(20))
# 每3个元素取一个
for i in range(0, len(data), 3):
print(data[i], end=' ')
# 0 3 6 9 12 15 18
五、range() vs 其他迭代方式
5.1 选择合适的迭代方式
data = ["apple", "banana", "orange", "grape", "kiwi"]
# 1. 只需要值 → 直接迭代
for item in data:
print(item)
# 2. 需要索引和值 → enumerate()
for i, item in enumerate(data):
print(f"{i}: {item}")
# 3. 只需要索引 → range(len())
for i in range(len(data)):
print(f"索引: {i}")
# 4. 需要修改原列表 → range(len())
for i in range(len(data)):
data[i] = data[i].upper()
# 5. 需要跳步 → range() 配合步长或切片
for i in range(0, len(data), 2):
print(data[i])
# 或者切片 + 直接迭代
for item in data[::2]:
print(item)
# 6. 需要反向 → reversed() 或 range(len()-1, -1, -1)
for item in reversed(data):
print(item)
# 7. 需要特定范围内的迭代 → range(start, stop)
for i in range(5, 10):
print(i)
5.2 range vs list 内存对比
import sys
# range对象的优势在循环中体现
# for i in range(10000000): # 只占用约48字节
# pass
# for i in list(range(10000000)): # 占用约80MB!不要这样做
# pass
# 对比不同大小的range和list
sizes = [100, 10000, 1000000]
for n in sizes:
r = range(n)
l = list(r)
print(f"n={n:>10,}: range={sys.getsizeof(r):>6} bytes, list={sys.getsizeof(l):>12,} bytes")
六、实战案例
6.1 进度条模拟器
import time
def simulate_progress(total, desc="处理中"):
"""模拟进度条 —— range控制迭代"""
bar_length = 30
for i in range(total + 1):
percent = i / total
filled = int(bar_length * percent)
bar = '█' * filled + '░' * (bar_length - filled)
print(f'\r{desc} |{bar}| {percent:.0%} ({i}/{total})', end='')
time.sleep(0.05)
print() # 换行
# simulate_progress(50, "下载中")
6.2 批量任务处理器
class BatchProcessor:
"""批量任务处理器 —— range控制批处理"""
def __init__(self, items, batch_size=100):
self.items = items
self.batch_size = batch_size
self.results = []
def process(self, worker_func):
"""分批处理所有元素"""
total = len(self.items)
batches = (total + self.batch_size - 1) // self.batch_size
for batch_idx in range(batches):
start = batch_idx * self.batch_size
end = min(start + self.batch_size, total)
batch = self.items[start:end]
print(f"处理批次 {batch_idx + 1}/{batches} "
f"(元素 {start}-{end-1}, 共{len(batch)}个)")
# 处理批次
batch_results = [worker_func(item) for item in batch]
self.results.extend(batch_results)
# 模拟批次间暂停
time.sleep(0.1)
print(f"\n✅ 全部处理完成: {len(self.results)} 个结果")
return self.results
# 使用
# processor = BatchProcessor(range(1000), batch_size=150)
# results = processor.process(lambda x: x ** 2)
七、本章小结
本文我们全面掌握了range()函数:
- 三种参数形式:
range(stop)从0到stop-1;range(start, stop)从start到stop-1;range(start, stop, step)以step步长递增/递减。 - 高效特性:惰性计算(不存储所有元素)、O(1)成员检查、支持索引和切片、内存占用极低(约48字节)。
- 实用技巧:重复N次用
for _ in range(n)、倒序用reversed(range(n))或range(n-1, -1, -1)、跳步用步长参数。 - 何时用range(len()):修改原列表元素、操作相邻元素、跳跃遍历——这些场景下range(len())是合理的。但对于简单的遍历值,直接用
for item in items更Pythonic。
range()是for循环的最佳搭档,理解它的每一个参数和特性,能让你写出更高效、更优雅的循环代码。⌨️ 下一篇文章,我们将学习enumerate()——让带索引的遍历更加优雅。
到此这篇关于Python基础指南之range()函数的参数详解与高效用法的文章就介绍到这了,更多相关Python range()函数用法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
详解win10下pytorch-gpu安装以及CUDA详细安装过程
这篇文章主要介绍了win10下pytorch-gpu安装以及CUDA详细安装过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2021-01-01
Python常用内置模块日志、随机数、时间、OS与JSON详解
本文介绍了Python开发中常用的五大模块:日志、随机数、时间、系统文件操作及JSON数据处理,详细讲解了各模块的的常见函数及其应用场景,需要的朋友可以参考下2026-05-05


最新评论