当前位置:首页 > MySQL教程 > 正文内容

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

搜教程4年前 (2019-12-01)MySQL教程234
本篇文章给人人带来的内容是关于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网别的相干文章!

扫描二维码推送至手机访问。

版权声明:本文由搜教程网发布,如需转载请注明出处。

本文链接:https://www.sojiaocheng.cn/15685.html

分享给朋友:

“range()是什么?为何不生产迭代器?【MySQL教程】,mysql,django,linux,flask,python” 的相关文章

MYSQL数据库服务器高iowait怎样优化【MySQL教程】,iowait,MYSQL,服务器

一个数据库服务器高iowait的优化案例 1.开辟反应某一测试环境sql运转迟缓,而在其他测试环境该sql运转很快。两个环境其设置雷同,均只布置了mysql服务器。 2.实行top敕令发明sql运转迟缓的机械上磁盘iowait较sql运转较快的机械凌驾许多。推想这是以致sql运转迟缓的主因,...

Mysql相干操纵有哪些【MySQL教程】,Mysql,哪些,相关

Mysql相干操纵有哪些【MySQL教程】,Mysql,哪些,相关

1》建立数据库:   语法:create database 数据库名;   语法:show databases 检察已存在数据库   举例:    Mysql->create database zytest; 注重每一条要以;号末端     Mysql->show d...

mysql5.1 command line client 登录时涌现闪退怎样处理【MySQL教程】,mysql5.1,command,client

由于长时间没有运用mysql command line client。今天在运用时,翻开界面,输入暗码后就涌现了闪退,同时workbench平台也显现不能衔接数据库。起首我照着百度试了一下,觉察在“计算机“-->"治理"(右键)-->“效劳”下,没有找到mysql有关的效劳。 处理办法以...

怎样竖立可打印中文的数据库【MySQL教程】,数据库,中文,打印

平常的数据库的字符型数据的编码都是 latinl,这是不支撑中文的 而支撑中文的字符编码是utf-8和gbk 要想让数据库里的表能够显现中文就必须在竖立数据库的时刻指定字符编码 1 create database bb charset=utf8; 或许 1 1 create d...

MySQL两大存储引擎InnoDB与MyISAM的区分【MySQL教程】,InnoDB,MySQL,引擎

1.InnoDB存储引擎 MySQL5.5中InnoDB成为默许的存储引擎。InnoDB是事件型存储引擎,被设想用来处置惩罚大批的短时间事件。它的机能和自动崩溃恢复特征,使得它在非事件场景中也很盛行。 所以可以这么说:“除非须要用到某些InnoDB不具备的特征,而且没有其他方法可以替换,...

关于MySQL竖立新用户并受权的要领【MySQL教程】,MySQL,授权,用户

竖立用户的语法: Create user `username`@host [Identified by [password] `password`]; Username:用户名 Host:主机名,当地主机可以用localhost或许ip地点,然则其他电脑必须用...