百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

迭代器杂谈:range对象为啥不是迭代器?他到底是是什么?

yuyutoo 2025-03-24 22:21 4 浏览 0 评论

当说起Python里面的高级特性时,就不能不提迭代器(Iterators)



迭代器到底有优秀

举个例子:

python中内置的方法有很多,Python2 中zip() 、enumerate()、map()、filter() 和 reversed() 等函数返回的是列表,在python3中他们的返回结果都变成了迭代器,

惰性计算,节省内存,它们就像是处理数据的一把利器,特别是对付大数据的时候,简直就是神器!

Python2 中有 range() 和 xrange() 两种内置方法,在python3中都统一为range函数。

曾经我以为他返回的对象range对象也是迭代器,直到有一天我这样操作

a=range(5)
next(a)
TypeError: 'range' object is not an iterator

突然发现,range对象竟然只是可迭代对象,但是不是迭代器,因为它不支持next

同样作为python中的内置函数,为啥它没有像 map()、filter()等函数一样返回迭代器,而是返回可迭代对象呢

咱们今天就来聊聊range对象到底是啥!

range基础语法

在 Python 中,range() 是一个内置函数,主要用于生成一个不可变的整数序列,

Python2 中 range() 生成的是列表,本文基于Python3,生成的是可迭代对象

这个序列通常在 for 循环中用于控制循环的次数。

range(start, stop, step)

参数说明:start 是起始值(包含该值),stop 是结束值(不包含该值),step 是步长,即相邻两个数之间的差值,可以是正数或负数,但不能为 0。

a=range(1,10,2)
print(a)
for i in a:
	print(i)

range对象是什么

使用type函数查看range返回值,他是一个range对象

type(range(5))
range

官网的描述中,range 返回的是range对象是一个不可变的数字序列,通常用于在 for 循环中按特定次数进行循环。

The range type represents an immutable sequence of numbers and is commonly used for looping a specific number of times in for loops.

既然是不可变序列,那么和同样作为不可变序列的字符串和元组有什么区别吗

range 对象支持序列中绝大部分的操作,但是不支持拼接(concatenation)和重复(repetition)。

r1 = range(3)
r2 = range(3, 6)
# new_range = r1 + r2
TypeError: unsupported operand type(s) for +: 'range' and 'range'
# repeated_range = r1 * 2
TypeError: unsupported operand type(s) for *: 'map' and 'int'

很奇怪是不是:为什么字符串和元组支持上述两种操作,但是range 序列偏偏不支持呢?

虽然不可变序列不能直接修改,但是字符串和元组可以进行裁剪拼接,生成一个字符串副本,也达到了修改的目的了,为何 range 对象连这都不支持呢?

仔细研究range的语法我们会发现,range其实和数学中的等差数列差不多,有开始值和结束值,还有差值,他是严格的递增或递减序列,元素都是有序排列的。

而字符串和元组中的元素则是可以随机排列,顺序完全不影响。

由于 range 对象的元素必须遵循从起始值开始,以固定步长递增或递减的模式,拼接和重复操作会打破这种规则,所以 range 对象不支持这两种操作。

range对象到底是什么

官方文档在介绍range时明确给出了说明:有三种基本的序列类型:列表、元组和 range 对象。

专门用于处理二进制数据和文本字符串的其他序列类型

There are three basic sequence types: lists, tuples, and range objects.

Additional sequence types tailored for processing of binary data and text strings are described in dedicated sections.

没想到range对象级别这么高,竟然是基础的序列类型,和列表,元组同级

3,为什么range对象不是迭代器而是可迭代对象

搞明白了range 对象是什么,我们先看看迭代器和可迭代对象的异同点

相同点:

两者都属于惰性迭代,在 for-循环 遍历时,可迭代对象与迭代器的性能是一样的,

即它们都是惰性求值的,在空间复杂度与时间复杂度上并无差异。

不同的是:

迭代器属于可迭代对象,而可迭代对象却不一定都是迭代器,比如常见的容器,列表,元组,字典,集合等等。有__iter__魔法方法就属于可迭代对象,而迭代器同时还有__next__魔法方法,支持next方法,

next([1,2,3])
TypeError: 'list' object is not an iterator

迭代器不支持切片操作,即不支持__getitem__魔法方法,而可迭代对象可以切片操作

s=[1,2,3]
s[1]
2
m=map(lambda x:x+10,[1,2,3])
m[1]
TypeError: 'map' object is not subscriptable

迭代次数差异

迭代器只能迭代一次,一旦迭代完成对象就会变成空对象无法再迭代,如果要重复迭代,即需要重新创建一个迭代器,而可迭代对象,比如:列表元组支持重复迭代

在惰性计算,节约内存,提升效率方面,迭代器和可迭代对象,很难说哪个更有优势,

那range为什么返回迭代器而是返回可迭代对象呢?

因为在官方的定义中,它已经不仅仅是一个普通的内置函数了。

1,基础序列需要一个能生成更大序列的对象

虽然列表,元组都属于可迭代对象,但是列表,元组这些属于普通的序列,无法承载较大量的数据,因为这样会消耗内存空间。

这个时候range对象应运而生了,range 对象相较于普通列表或元组的优势在于,无论它所表示的范围大小如何,range 对象始终占用相同(较少)数量的内存(因为它仅存储起始值、终止值和步长值,并根据需要计算单个元素和子范围)。

The advantage of the range type over a regular list or tuple is that a range object will always take the same (small) amount of memory,

no matter the size of the range it represents (as it only stores the start, stop and step values, calculating individual items and subranges as needed).

列表,元组都属于可迭代对象,为了保持统一,range也返回可迭代对象了。

虽然没有和其他内置函数的返回结果保持统一,但是和同属可迭代对象的基础序列保持一致。

2,既然作为基础的序列,那就意味着会经常被用做基础的数据

迭代器属于一次性遍历,一旦迭代完就不能再迭代,如果要重新迭代必须重新创建一个迭代器,作为基础数据有很大的隐患,而 map()、filter() 这样的内置函数,本身他们的参数就是有一个可迭代对象,属于更高层级的加工后的数据,可以直接作为结果输出迭代器,对输出结果其实没有那么严格限制。

b=map(lambda x:x*10,range(3))
b

next(b)
0
next(b)
10
next(b)
20
next(b)
StopIteration
list(b)
[]

总的来说,range对象已经由一个普通的内置函数升级为基础的序列类型了,他要和同为基础序列的列表,元组的对象类型保持一致。

同时作为基础的数据类型,在被用来生成其他数据时,可迭代对象可以重复迭代,比迭代器更具有优势。

相关推荐

ETCD 故障恢复(etc常见故障)

概述Kubernetes集群外部ETCD节点故障,导致kube-apiserver无法启动。...

在Ubuntu 16.04 LTS服务器上安装FreeRADIUS和Daloradius的方法

FreeRADIUS为AAARadiusLinux下开源解决方案,DaloRadius为图形化web管理工具。...

如何排查服务器被黑客入侵的迹象(黑客 抓取服务器数据)

---排查服务器是否被黑客入侵需要系统性地检查多个关键点,以下是一份详细的排查指南,包含具体命令、工具和应对策略:---###**一、快速初步检查**####1.**检查异常登录记录**...

使用 Fail Ban 日志分析 SSH 攻击行为

通过分析`fail2ban`日志可以识别和应对SSH暴力破解等攻击行为。以下是详细的操作流程和关键分析方法:---###**一、Fail2ban日志位置**Fail2ban的日志路径因系统配置...

《5 个实用技巧,提升你的服务器安全性,避免被黑客盯上!》

服务器的安全性至关重要,特别是在如今网络攻击频繁的情况下。如果你的服务器存在漏洞,黑客可能会利用这些漏洞进行攻击,甚至窃取数据。今天我们就来聊聊5个实用技巧,帮助你提升服务器的安全性,让你的系统更...

聊聊Spring AI Alibaba的YuQueDocumentReader

序本文主要研究一下SpringAIAlibaba的YuQueDocumentReaderYuQueDocumentReader...

Mac Docker环境,利用Canal实现MySQL同步ES

Canal的使用使用docker环境安装mysql、canal、elasticsearch,基于binlog利用canal实现mysql的数据同步到elasticsearch中,并在springboo...

RustDesk:开源远程控制工具的技术架构与全场景部署实战

一、开源远程控制领域的革新者1.1行业痛点与解决方案...

长安汽车一代CS75Plus2020款安装高德地图7.5

不用破解原车机,一代CS75Plus2020款,安装车机版高德地图7.5,有红绿灯读秒!废话不多讲,安装步骤如下:一、在拨号状态输入:在电话拨号界面,输入:*#518200#*(进入安卓设置界面,...

Zookeeper使用详解之常见操作篇(zookeeper ui)

一、Zookeeper的数据结构对于ZooKeeper而言,其存储结构类似于文件系统,也是一个树形目录服务,并通过Key-Value键值对的形式进行数据存储。其中,Key由斜线间隔的路径元素构成。对...

zk源码—4.会话的实现原理一(会话层的基本功能是什么)

大纲1.创建会话...

Zookeeper 可观测性最佳实践(zookeeper能够确保)

Zookeeper介绍ZooKeeper是一个开源的分布式协调服务,用于管理和协调分布式系统中的节点。它提供了一种高效、可靠的方式来解决分布式系统中的常见问题,如数据同步、配置管理、命名服务和集群...

服务器密码错误被锁定怎么解决(服务器密码错几次锁)

#服务器密码错误被锁定解决方案当服务器因多次密码错误导致账户被锁定时,可以按照以下步骤进行排查和解决:##一、确认锁定状态###1.检查账户锁定状态(Linux)```bash#查看账户锁定...

zk基础—4.zk实现分布式功能(分布式zk的使用)

大纲1.zk实现数据发布订阅...

《死神魂魄觉醒》卡死问题终极解决方案:从原理到实战的深度解析

在《死神魂魄觉醒》的斩魄刀交锋中,游戏卡死犹如突现的虚圈屏障,阻断玩家与尸魂界的连接。本文将从技术架构、解决方案、预防策略三个维度,深度剖析卡死问题的成因与应对之策,助力玩家突破次元壁障,畅享灵魂共鸣...

取消回复欢迎 发表评论: