欢迎大家来到IT世界,在知识的湖畔探索吧!
当说起Python里面的高级特性时,就不能不提迭代器(Iterators)

欢迎大家来到IT世界,在知识的湖畔探索吧!
迭代器到底有优秀
举个例子:
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
欢迎大家来到IT世界,在知识的湖畔探索吧!
突然发现,range对象竟然只是可迭代对象,但是不是迭代器,因为它不支持next
同样作为python中的内置函数,为啥它没有像 map()、filter()等函数一样返回迭代器,而是返回可迭代对象呢
咱们今天就来聊聊range对象到底是啥!
range基础语法
在 Python 中,range() 是一个内置函数,主要用于生成一个不可变的整数序列,
Python2 中 range() 生成的是列表,本文基于Python3,生成的是可迭代对象
这个序列通常在 for 循环中用于控制循环的次数。
range(start, stop, step)
参数说明:start 是起始值(包含该值),stop 是结束值(不包含该值),step 是步长,即相邻两个数之间的差值,可以是正数或负数,但不能为 0。
欢迎大家来到IT世界,在知识的湖畔探索吧!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)。
欢迎大家来到IT世界,在知识的湖畔探索吧!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__魔法方法,而可迭代对象可以切片操作
欢迎大家来到IT世界,在知识的湖畔探索吧!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
总的来说,range对象已经由一个普通的内置函数升级为基础的序列类型了,他要和同为基础序列的列表,元组的对象类型保持一致。
同时作为基础的数据类型,在被用来生成其他数据时,可迭代对象可以重复迭代,比迭代器更具有优势。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/116063.html