百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>数据库> range()有哪些?为何不生产迭代器?
分享文章到:

range()有哪些?为何不生产迭代器?

发布时间:08/01 来源:未知 浏览: 关键词:
本篇文章给大家带来的内容是对于range()有哪些?为何不生产迭代器?有一定的参照 价值,有需要的伴侣可以参照 一下,但愿对你有所帮忙。 本篇文章给大家带来的内容是对于range()有哪些?为何不生产迭代器?有一定的参照 价值,有需要的伴侣可以参照 一下,但愿对你有所帮忙。

迭代器是 23 种设计模式中最常用的一种(之一),在 Python 中随处可见它的身影,我们时常用到它,但是却纷歧定意识到它的存在。在对于迭代器的系列文章中(链会见文末),我至少提到了 23 种生成迭代器的办法。有些办法是专门用于生成迭代器的,还有一些办法则是为理解决另外题目而“黑暗”运用到迭代器。

在系统学习迭代器以前,我不断认为 range() 办法也是用于生成迭代器的,此刻却忽然发明,它生成的只是可迭代对象,而并不是迭代器! (PS:Python2 中 range() 生成的是列表,本文基于Python3,生成的是可迭代对象)

于是,我有了这样的疑难:为何 range() 不生成迭代器呢?在查寻答案的历程中,我发明本人对 range 类型的相识存在一些误区。因而,本文将和大家全面地相识一下 range ,等待与你共同窗习进步。

1、range() 有哪些?

它的语法:range(start, stop [,step]) ;start 指的是计数起始值,默许是 0;stop 指的是计数完毕值,但不包含 stop ;step 是步长,默许为 1,不成认为 0 。range() 办法生成一段左闭右开的整数范畴。

>>> a = range(5)  # 即 range(0,5)
>>> a
range(0, 5)
>>> len(a)
5
>>> for x in a:
>>>     print(x,end=" ")
0 1 2 3 4

关于 range() 函数,有几个注意点:(1)它表示的是左闭右开区间;(2)它接收的参数必需是整数,可以是负数,但不克不及是浮点数等其它类型;(3)它是不成变的序列类型,可以进行推断元素、查寻元素、切片等操纵,但不克不及修改元素;(4)它是可迭代对象,却不是迭代器。

# (1)左闭右开
>>> for i in range(3, 6):
>>>     print(i,end=" ")
3 4 5

# (2)参数类型
>>> for i in range(-8, -2, 2):
>>>     print(i,end=" ")
-8 -6 -4
>>> range(2.2)
----------------------------
TypeError    Traceback (most recent call last)
...
TypeError: 'float' object cannot be interpreted as an integer

# (3)序列操纵
>>> b = range(1,10)
>>> b[0]
1
>>> b[:-3]
range(1, 7)
>>> b[0] = 2
TypeError  Traceback (most recent call last)
...
TypeError: 'range' object does not support item assignment

# (4)不是迭代器
>>> hasattr(range(3),'__iter__')
True
>>> hasattr(range(3),'__next__')
False
>>> hasattr(iter(range(3)),'__next__')
True

2、 为何range()不生产迭代器?

可以获得迭代器的内置办法许多,例如 zip() 、enumerate()、map()、filter() 和 reversed() 等等,但是像 range() 这样仅仅得到的是可迭代对象的办法就司空见惯了(如有反例,欢送奉告)。这就是我存在见识误区的地方。

在 for-轮回 遍历时,可迭代对象与迭代器的机能是同样的,即它们都是惰性求值的,在空间复杂度与工夫复杂度上并无悬殊。我曾具体过两者的差别是“一同两不一样”:雷同的是都可惰性迭代,不一样的是可迭代对象不支撑自遍历(即next()办法),而迭代器自身不支撑切片(即__getitem__() 办法)。

虽然有这些差别,但很难得出结论说它们哪个更优。此刻奥妙之处就在于,为何给 5 种内置办法都设计了迭代器,偏偏给 range() 办法设计的就是可迭代对象呢?把它们都同一起来,不是更好么?

事实上,Pyhton 为了标准性就干过不少这种事,例如,Python2 中有 range() 和 xrange() 两种办法,而 Python3 就干掉了其中一种,还用了“李代桃僵”法。为何不更标准点,令 range() 生成的是迭代器呢?

对于这个题目,我没寻到官方解释,下列纯属个人观念

zip() 等办法都需要接收肯定的可迭代对象的参数,是对它们的一种再加工的历程,因而也但愿即将产出肯定的效果来,所以 Python 开发者就设计了这个效果是迭代器。这样还有一个益处,即当作为参数的可迭代对象产生变化的时候,作为效果的迭代器由于是耗损型的,不会被差错地运用。

而 range() 办法就不一样了,它接收的参数不是可迭代对象,自身是一种初次加工的历程,所以设计它为可迭代对象,既可以直接运用,也可以用于其它再加工用法。例如,zip() 等办法就完全可以接收 range 类型的参数。

>>> for i in zip(range(1,6,2), range(2,7,2)):
>>>    print(i, end="")
(1, 2)(3, 4)(5, 6)

也就是说,range() 办法作为一种低级生产者,它生产的原料自身就有很大用法,早早把它变为迭代器的话,无疑是一种多此一举的行为。

关于这种解读,你可否觉得有原理呢?欢送就这个话题与我探究。

3、range 类型有哪些?

以上是我对“为何range()不发生迭代器”的一种解答。顺着这个思绪,我研究了一下它发生的 range 对象,一研究就发明,这个 range 对象也并不简略。

第一蹊跷怪僻的一点就是,它居然是不成变序列!我从未注意过这一点。虽然说,我从未想过修改 range() 的值,但这一不成修改的特性还是令我惊叹。

翻看文档,官方是这样明白划分的——有三种根本的序列类型:列表、元组和范畴(range)对象。(There are three basic sequence types: lists, tuples, and range objects.)

这我倒不断没注意,本来 range 类型竟然跟列表和元组是同样地位的根基序列!我不断记挂着字符串是不成变的序列类型,未曾想,这里还有一名不成变的序列类型呢。

那 range 序列跟其它序列类型有什么悬殊呢?

普通序列都支撑的操纵有 12 种,在《你真的晓得Python的字符串有哪些吗?》这篇文章里提到过。range 序列只支撑其中的 10 种,不支撑进行加法拼接与乘法反复。

>>> range(2) + range(3)
-----------------------------------------
TypeError  Traceback (most recent call last)
...
TypeError: unsupported operand type(s) for +: 'range' and 'range'

>>> range(2)*2
-----------------------------------------
TypeError  Traceback (most recent call last)
...
TypeError: unsupported operand type(s) for *: 'range' and 'int'

那么题目来了:一样是不成变序列,为何字符串和元组就支撑上述两种操纵,而偏偏 range 序列不支撑呢?虽然不克不及直接修改不成变序列,但我们可以将它们拷贝到新的序列上进行操纵啊,为什么 range 对象连这都不支撑呢?

且看官方文档的解释:

...due to the fact that range objects can only represent sequences that follow a strict pattern and repetition and concatenation will usually violate that pattern.

缘由是 range 对象仅仅表示一个遵循着严厉模式的序列,而反复与拼接平常会毁坏这种模式...

题目的关键就在于 range 序列的 pattern,细心想想,其实它表示的就是一个等差数列啊(喵,高中数学见识没忘...),拼接两个等差数列,或者反复拼接一个等差数列,想想的确不当,这就是为啥 range 类型不支撑这两个操纵的缘由了。由此推论,其它修改行动也会毁坏等差数列构造,所以通通不给修改就是了。

4、小结

回忆全文,我得到了两个偏冷门的结论:range 是可迭代对象而不是迭代器;range 对象是不成变的等差序列。

若纯正看结论的话,你或许没有感到,也许还会说这没啥了不起啊。但要是我追问,为何 range 不是迭代器呢,为何 range 是不成变序列呢?对这俩题目,你可否还能答出个无懈可击的设计思想呢?(PS:我决议了,如有时机面试他人,我须要问这两个题目的嘿~)

因为 range 对象这细微而成心思的特性,我觉得这篇文章写得值了。本文是作为迭代器系列文章的一篇来写的,所以关于迭代器的根基见识介绍未几,欢送查看以前的文章。别的,还有一种特别的迭代器也值得独自成文,那就是生成器了,敬请等待后续推文哦~

以上就是range()有哪些?为何不生产迭代器?的细致内容,更多请关注 百分百源码网 其它相干文章!

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有151人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板