dw做的网站如何上传云服务器,建设银行网站会员怎么注册,怎么做网站原型,禅城网站建设多少钱嗨喽~大家好呀#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取
迭代器是 23 种设计模式中最常用的一种#xff08;之一#xff09;#xff0c;在 Python 中随处可见它的身影#xff0c;我们经常用到它#xff0c;但是却不…嗨喽~大家好呀这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取
迭代器是 23 种设计模式中最常用的一种之一在 Python 中随处可见它的身影我们经常用到它但是却不一定意识到它的存在。
在系统学习迭代器之前我一直以为 range() 方法也是用于生成迭代器的现在却突然发现它生成的只是可迭代对象而并不是迭代器 PSPython2 中 range() 生成的是列表本文基于Python3生成的是可迭代对象
于是我有了这样的疑问为什么 range() 不生成迭代器呢
在查找答案的过程中我发现自己对 range 类型的认识存在一些误区。因此本文将和大家全面地认识一下 range 期待与你共同学习进步。
1、range() 是什么
它的语法range(start, stop [,step]) start 指的是计数起始值默认是 0 stop 指的是计数结束值但不包括 stop step 是步长默认为 1不可以为 0 。 range() 方法生成一段左闭右开的整数范围。 对于 range() 函数有几个注意点
1它表示的是左闭右开区间
2它接收的参数必须是整数可以是负数但不能是浮点数等其它类型
3它是不可变的序列类型可以进行判断元素、查找元素、切片等操作但不能修改元素
4它是可迭代对象却不是迭代器。 2、 为什么range()不生产迭代器
可以获得迭代器的内置方法很多例如 zip() 、enumerate()、map()、filter() 和 reversed() 等等但是像 range() 这样仅仅得到的是可迭代对象的方法就绝无仅有了若有反例欢迎告知。
这就是我存在知识误区的地方。
在 for-循环 遍历时可迭代对象与迭代器的性能是一样的即它们都是惰性求值的在空间复杂度与时间复杂度上并无差异。
我曾概括过两者的差别是“一同两不同” 相同的是都可惰性迭代 不同的是可迭代对象不支持自遍历即next()方法而迭代器本身不支持切片即__getitem__() 方法。
虽然有这些差别但很难得出结论说它们哪个更优。
现在微妙之处就在于为什么给 5 种内置方法都设计了迭代器偏偏给 range() 方法设计的就是可迭代对象呢把它们都统一起来不是更好么
事实上Pyhton 为了规范性就干过不少这种事例如Python2 中有 range() 和 xrange() 两种方法而 Python3 就干掉了其中一种还用了“李代桃僵”法。
为什么不更规范点令 range() 生成的是迭代器呢
关于这个问题我没找到官方解释以下纯属个人观点 。
zip() 等方法都需要接收确定的可迭代对象的参数是对它们的一种再加工的过程因此也希望马上产出确定的结果来所以 Python 开发者就设计了这个结果是迭代器。
这样还有一个好处即当作为参数的可迭代对象发生变化的时候作为结果的迭代器因为是消耗型的不会被错误地使用。
而 range() 方法就不同了它接收的参数不是可迭代对象本身是一种初次加工的过程所以设计它为可迭代对象既可以直接使用也可以用于其它再加工用途。
例如zip() 等方法就完全可以接收 range 类型的参数。 也就是说range() 方法作为一种初级生产者它生产的原料本身就有很大用途早早把它变为迭代器的话无疑是一种画蛇添足的行为。
对于这种解读你是否觉得有道理呢欢迎就这个话题与我探讨。 遇到问题没人解答小编创建了一个Python学习交流QQ群926207505
寻找有志同道合的小伙伴互帮互助,群里还有不错的视频学习教程和PDF电子书3、range 类型是什么
以上是我对“为什么range()不产生迭代器”的一种解答。
顺着这个思路我研究了一下它产生的 range 对象一研究就发现这个 range 对象也并不简单。
首先奇怪的一点就是它竟然是不可变序列
虽然说我从未想过修改 range() 的值但这一不可修改的特性还是令我惊讶。
翻看文档官方是这样明确划分的——有三种基本的序列类型列表、元组和范围range对象。There are three basic sequence types: lists, tuples, and range objects.
这我倒一直没注意原来 range 类型居然跟列表和元组是一样地位的基础序列
我一直记挂着字符串是不可变的序列类型不曾想这里还有一位不可变的序列类型呢。
那 range 序列跟其它序列类型有什么差异呢
普通序列都支持的操作有 12 种。range 序列只支持其中的 10 种不支持进行加法拼接与乘法重复。 那么问题来了同样是不可变序列为什么字符串和元组就支持上述两种操作而偏偏 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 是不可变序列呢
对这俩问题你是否还能答出个自圆其说的设计思想呢
本文是作为迭代器系列文章的一篇来写的所以对于迭代器的基础知识介绍不多另外还有一种特殊的迭代器也值得单独成文那就是生成器了。
尾语
最后感谢你观看我的文章呐~本次航班到这里就结束啦
希望本篇文章有对你带来帮助 有学习到一点知识~
躲起来的星星也在努力发光你也要努力加油让我们一起努力叭。 最后宣传一下呀~更多源码、资料、素材、解答、交流皆点击下方名片获取呀