旗下导航:搜·么
当前位置:网站首页 > MySQL教程 > 正文

range()是什么?为何不生产迭代器?【MySQL教程】,mysql,django,linux,flask,python

作者:搜教程发布时间:2019-12-01分类:MySQL教程浏览:57评论:0


导读:本篇文章给人人带来的内容是关于range()是什么?为什么不生产迭代器?有肯定的参考价值,有须要的朋侪能够参考一下,愿望对你有所协助。迭代器是23种设想形式中最常常运用...
本篇文章给人人带来的内容是关于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()是什么?为什么不生产迭代器?的细致内容,更多请关注ki4网别的相干文章!

标签:mysqldjangolinuxflaskpython


欢迎 发表评论: