Python中的range()函数-从入门到精通

2024-09-05 21:04

本文主要是介绍Python中的range()函数-从入门到精通,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

你是否曾经好奇过,为什么Python中的range(100)只生成到99?或者,如何用range()创建一个倒序的数列?今天,让我们深入探讨Python中这个看似简单却蕴含无限可能的range()函数!

在这里插入图片描述

range()函数简介

range()函数是Python中一个强大而灵活的内置函数,它主要用于生成一个整数序列。无论你是初学者还是经验丰富的开发者,掌握range()的使用都能让你的代码更加简洁高效。

range()函数的基本语法如下:

range(stop)
range(start, stop[, step])

看起来很简单,对吧?但是,range()的魔力远不止于此。让我们一步步揭开它的神秘面纱!
image.png

range()的基本用法

1. 生成简单序列

最基本的用法是生成一个从0开始的整数序列:

for i in range(5):print(i)# 输出:
# 0
# 1
# 2
# 3
# 4

注意,range(5)生成的序列不包括5本身。这是因为range()函数遵循Python的"左闭右开"原则。
image.png

2. 指定起始值

如果你想从非零值开始,可以这样做:

for i in range(2, 7):print(i)# 输出:
# 2
# 3
# 4
# 5
# 6

3. 使用步长

range()函数的第三个参数允许你指定步长:

for i in range(0, 10, 2):print(i)# 输出:
# 0
# 2
# 4
# 6
# 8

这个例子生成了一个偶数序列。

range()的进阶技巧

image.png

1. 创建递减序列

你可以通过使用负步长来创建递减序列:

for i in range(10, 0, -1):print(i)# 输出:
# 10
# 9
# 8
# 7
# 6
# 5
# 4
# 3
# 2
# 1

这个技巧在需要倒计时或逆序遍历时非常有用。

2. 生成字符序列

虽然range()主要用于整数,但我们可以结合ord()和chr()函数来生成字符序列:

for i in range(ord('A'), ord('Z')+1):print(chr(i), end=' ')# 输出: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

这个例子生成了从A到Z的字母序列。

3. 使用range()创建列表

虽然range()本身返回的是一个可迭代对象,但我们可以轻松地将其转换为列表:

numbers = list(range(1, 6))
print(numbers)  # 输出: [1, 2, 3, 4, 5]

这在需要快速创建数字列表时非常有用。

4. 结合zip()函数使用

range()可以与zip()函数结合使用,创建带索引的迭代:

fruits = ['apple', 'banana', 'cherry']
for i, fruit in zip(range(1, len(fruits)+1), fruits):print(f"{i}. {fruit}")# 输出:
# 1. apple
# 2. banana
# 3. cherry

这种技巧在需要为列表元素添加序号时特别有用。

range()的内部实现

image.png

range()函数的内部实现是一个非常有趣的话题。虽然它看起来像是生成了一个完整的序列,但实际上range()对象是"惰性"的,只有在被迭代时才会生成数字。

让我们通过一个简单的例子来理解这一点:

r = range(1, 1000000)
print(r)  # 输出: range(1, 1000000)
print(type(r))  # 输出: <class 'range'>
print(sys.getsizeof(r))  # 输出: 48 (可能因Python版本而异)

尽管我们创建了一个包含近百万个数的range对象,但它占用的内存非常小。这是因为range对象只存储了start, stop和step值,而不是实际的数字序列。

range对象的特性

  1. 不可变性: range对象是不可变的。一旦创建,你就不能修改它的start, stop或step值。

  2. 支持索引和切片: 虽然range对象不是列表,但它支持索引和切片操作。

r = range(0, 10)
print(r[5])  # 输出: 5
print(r[2:5])  # 输出: range(2, 5)
  1. 支持成员检测: 你可以使用in运算符检查一个数是否在range中。
r = range(0, 10, 2)
print(4 in r)  # 输出: True
print(5 in r)  # 输出: False
  1. 可重复使用: 因为range对象只在需要时才生成数字,所以你可以多次迭代同一个range对象而不会占用额外的内存。
r = range(5)
for i in r:print(i)
# 再次使用
for i in r:print(i)

range()的时间复杂度

range()函数的大多数操作都具有O(1)的时间复杂度,这意味着无论range包含多少个数,这些操作的执行时间都是常数级的。

  • 创建range对象: O(1)
  • 检查成员资格 (in 运算符): O(1)
  • 获取长度 (len()): O(1)
  • 获取任意元素 (索引): O(1)

这种高效的实现使得range()在处理大范围的数字序列时特别有用。

range()的性能优化

image.png

了解了range()的内部实现后,我们可以更好地利用它来优化我们的代码。以下是一些性能优化的技巧:

1. 使用range()替代列表

当你需要遍历一个大范围的数字时,使用range()比使用列表要高效得多。

# 低效的方式
for i in list(range(1000000)):pass# 高效的方式
for i in range(1000000):pass

第二种方式不仅运行更快,而且内存使用量也大大减少。

2. 在循环中避免重复计算range()

如果你在循环中多次使用相同的range,最好将其赋值给一个变量:

# 低效的方式
for i in range(len(some_list)):print(some_list[i])# 高效的方式
n = len(some_list)
for i in range(n):print(some_list[i])

这样可以避免在每次循环迭代时都重新计算len(some_list)。

3. 利用range()的不可变性

因为range对象是不可变的,所以你可以安全地在多个地方重用同一个range对象:

r = range(10)def func1():for i in r:print(i)def func2():return list(r)# r 可以安全地在多个函数中重用

4. 使用range()进行切片

当你需要对一个大列表进行切片操作时,先使用range()可以避免创建中间列表:

big_list = list(range(1000000))# 低效的方式
print(big_list[10000:10010])# 高效的方式
r = range(1000000)
print(list(r[10000:10010]))

第二种方式避免了创建整个big_list,只在最后才创建了一个10个元素的小列表。

range()的常见陷阱和解决方案

尽管range()函数非常强大和灵活,但在使用过程中也存在一些常见的陷阱。让我们来看看这些陷阱以及如何避免它们。
image.png

1. 忘记range()是左闭右开区间

这可能是使用range()时最常见的错误。记住,range(start, stop)生成的序列不包括stop值。

# 错误的用法
for i in range(1, 5):print(i)  # 输出: 1, 2, 3, 4 (没有5)# 正确的用法
for i in range(1, 6):print(i)  # 输出: 1, 2, 3, 4, 5

解决方案: 当你想包括结束值时,记得在stop参数上加1。

2. 使用浮点数作为步长

range()函数只接受整数参数。使用浮点数会导致TypeError。

# 错误的用法
for i in range(0, 1, 0.1):print(i)  # 抛出 TypeError# 正确的用法 (如果真的需要浮点数步长)
import numpy as np
for i in np.arange(0, 1, 0.1):print(i)

解决方案: 如果你需要浮点数步长,考虑使用numpy的arange()函数。

3. 在range()中使用变量时的意外行为

当你在range()中使用变量时,这些变量的值在range()创建时就被固定了。

n = 5
r = range(n)
n = 10
print(list(r))  # 输出: [0, 1, 2, 3, 4] (而不是 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

解决方案: 如果你需要动态范围,考虑使用生成器表达式或者在每次需要时重新创建range对象。

4. 在反向range中使用错误的步长

创建反向range时,很容易忘记使用负步长。

# 错误的用法
for i in range(10, 0):print(i)  # 不会打印任何东西# 正确的用法
for i in range(10, 0, -1):print(i)  # 输出: 10, 9, 8, ..., 1

解决方案: 当创建反向range时,记得指定负步长。

5. 过度使用range()导致的可读性问题

虽然range()很强大,但过度使用可能导致代码难以理解。

# 难以理解的代码
for i in range(len(some_list)):print(some_list[i])# 更易读的代码
for item in some_list:print(item)

解决方案: 当简单迭代列表元素时,直接使用for-in循环。只有当你真正需要索引时,才使用range(len(…))。

6. 在大范围上使用list(range())

将range()直接转换为列表可能会占用大量内存。

# 可能导致内存错误
big_list = list(range(10**8))# 更安全的方法
for i in range(10**8):# 处理 i

解决方案: 除非确实需要列表,否则直接迭代range对象。

range()在实际项目中的应用

range()函数不仅仅是用于简单的循环,它在实际项目中有着广泛的应用。让我们探讨一些实际的使用场景。
image.png

1. 分页实现

在web开发中,range()常用于实现分页功能:

def paginate(items, page_number, items_per_page):start = (page_number - 1) * items_per_pageend = start + items_per_pagereturn items[start:end]all_items = list(range(100))  # 假设我们有100个项目
page_3 = paginate(all_items, page_number=3, items_per_page=10)
print(page_3)  # 输出: [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]

这个例子展示了如何使用range()的特性来实现简单的分页功能。

2. 批量处理

当处理大量数据时,range()可以用于创建批次:

def process_in_batches(items, batch_size=1000):for i in range(0, len(items), batch_size):batch = items[i:i+batch_size]# 处理这个批次process_batch(batch)# 假设我们有一个大列表需要处理
big_data = list(range(1000000))
process_in_batches(big_data)

这种方法可以有效地控制内存使用,特别是在处理非常大的数据集时。

3. 创建数字ID或序列号

range()函数非常适合创建唯一的数字ID或序列号:

class Product:id_generator = range(1, 10000).__iter__()def __init__(self, name):self.id = next(Product.id_generator)self.name = nameproducts = [Product(f"Product_{i}") for i in range(10)]
for product in products:print(f"ID: {product.id}, Name: {product.name}")

这个例子展示了如何使用range()创建一个简单的ID生成器。

4. 时间序列生成

在数据分析或时间序列处理中,range()可以用来生成日期范围:

from datetime import date, timedeltadef date_range(start_date, end_date):for n in range(int((end_date - start_date).days)):yield start_date + timedelta(n)start_date = date(2023, 1, 1)
end_date = date(2023, 1, 10)for d in date_range(start_date, end_date):print(d)

这个函数使用range()生成一系列日期,这在处理时间序列数据时非常有用。

5. 创建测试数据

在编写单元测试或创建模拟数据时,range()是一个强大的工具:

import randomdef generate_test_data(n):return [{'id': i,'name': f'User_{i}','age': random.randint(18, 80),'score': random.uniform(0, 100)}for i in range(n)]test_data = generate_test_data(1000)
print(test_data[:5])  # 打印前5个测试数据

这个例子展示了如何使用range()快速生成大量结构化的测试数据。

6. 实现简单的进度条

range()可以用来实现简单的命令行进度条:

import timedef progress_bar(iterable, total=None, prefix='', suffix='', decimals=1, length=50, fill='█', print_end="\r"):total = total or len(iterable)for i, item in enumerate(iterable):percent = ("{0:." + str(decimals) + "f}").format(100 * (i / float(total)))filled_length = int(length * i // total)bar = fill * filled_length + '-' * (length - filled_length)print(f'\r{prefix} |{bar}| {percent}% {suffix}', end=print_end)yield itemprint()# 使用示例
for _ in progress_bar(range(1000), total=1000, prefix='Progress:', suffix='Complete', length=50):time.sleep(0.01)  # 模拟一些处理时间

这个进度条使用range()来跟踪和显示长时间运行任务的进度。

range总结

image.png

通过深入探讨Python中的range()函数,我们不仅了解了它的基本用法,还发现了它在各种实际应用中的潜力。从简单的循环到复杂的数据处理,range()都展现出了其强大的功能和灵活性。

让我们回顾一下我们学到的关键点:

  1. range()函数是一个强大的工具,用于生成整数序列。
  2. 它的基本语法简单,但可以通过不同的参数组合实现复杂的序列生成。
  3. range()对象是"惰性"的,这使得它在处理大范围数字时非常高效。
  4. 我们可以利用range()的特性来优化代码性能,特别是在处理大量数据时。
  5. 虽然强大,但使用range()时也需要注意一些常见的陷阱,如左闭右开区间的特性。
  6. 在实际项目中,range()的应用非常广泛,从分页实现到创建测试数据,再到实现简单的进度条。

掌握range()函数不仅能让你的代码更加简洁高效,还能帮助你更好地理解Python中的迭代器和生成器概念。随着你在Python编程中的深入,你会发现range()函数在各种场景下都有其独特的应用价值。

希望这篇深入探讨能够帮助你更好地理解和使用Python中的range()函数。记住,编程的魅力在于不断学习和探索,而像range()这样看似简单的函数往往蕴含着无限的可能性。继续探索,继续编码,你会发现更多Python的精彩之处!

这篇关于Python中的range()函数-从入门到精通的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1140062

相关文章

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

Python+PyQt5实现多屏幕协同播放功能

《Python+PyQt5实现多屏幕协同播放功能》在现代会议展示、数字广告、展览展示等场景中,多屏幕协同播放已成为刚需,下面我们就来看看如何利用Python和PyQt5开发一套功能强大的跨屏播控系统吧... 目录一、项目概述:突破传统播放限制二、核心技术解析2.1 多屏管理机制2.2 播放引擎设计2.3 专

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

在C#中调用Python代码的两种实现方式

《在C#中调用Python代码的两种实现方式》:本文主要介绍在C#中调用Python代码的两种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#调用python代码的方式1. 使用 Python.NET2. 使用外部进程调用 Python 脚本总结C#调

Python下载Pandas包的步骤

《Python下载Pandas包的步骤》:本文主要介绍Python下载Pandas包的步骤,在python中安装pandas库,我采取的方法是用PIP的方法在Python目标位置进行安装,本文给大... 目录安装步骤1、首先找到我们安装python的目录2、使用命令行到Python安装目录下3、我们回到Py

Python GUI框架中的PyQt详解

《PythonGUI框架中的PyQt详解》PyQt是Python语言中最强大且广泛应用的GUI框架之一,基于Qt库的Python绑定实现,本文将深入解析PyQt的核心模块,并通过代码示例展示其应用场... 目录一、PyQt核心模块概览二、核心模块详解与示例1. QtCore - 核心基础模块2. QtWid