mid函数和replace函数的区别,Java replace方法

  mid函数和replace函数的区别,Java replace方法

  迭代器是最常用的设计模式之一,在Python中随处可见。我们经常使用它,却不一定意识到它的存在。在一系列关于迭代器的文章中(链接见文章末尾),我提到了至少23种生成迭代器的方法。有些方法是专门用来生成迭代器的,有些则是“偷偷”用迭代器来解决其他问题。

  在系统学习迭代器之前,我一直以为range()方法也是用来生成迭代器的,现在突然发现它只生成迭代器,不生成迭代器!(Python 2中的PS: range()生成列表,本文基于Python3,生成迭代对象)

  所以,我有这个问题:为什么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()这样只获取iterable对象的方法只有一个(如果有反例,请告知)。这就是我的知识出错的地方。

  在for- loop遍历中,迭代器和迭代器的性能是一样的,就是都是惰性求值,在空间复杂度和时间复杂度上没有区别。我总结了一下,两者的区别是“两个区别在一起”:相同的是可以惰性迭代,不同的是iterable对象不支持自遍历(即next()方法),而迭代器本身不支持切片(即getitem()方法)。

  虽然有这些区别,但是很难断定哪个更好。现在微妙之处在于,为什么迭代器是为所有五个内置方法设计的,而range()方法却被设计成可迭代对象?把他们都统一起来不是更好吗?

  事实上,Pyhton为了标准化已经做了很多这样的事情。比如Python2有两个方法,range()和xrange(),而Python3杀了其中一个,用的是“以桃代桃”的方法。为什么不更标准一点,让range()生成迭代器?

  关于这个问题,我还没有找到官方的解释。以下纯属我个人观点。

  zip()等方法都需要接收某些iterable对象的参数,这是一个对它们进行再处理的过程。所以,他们也想立刻产生一定的结果,所以Python开发者把这个结果设计成了迭代器。这也有一个好处,当作为参数的iterable对象改变时,结果迭代器不会被错误地使用,因为它是消耗性的。

  range()方法不同。它接收的参数不是迭代的对象,而是一个初始处理的过程。因此,它被设计为迭代对象,可以直接使用或用于其他再处理目的。例如,zip()这样的方法可以完全接收range类型的参数。

  图像

  也就是说,range()方法是一个初级生产者,它生产的原料有很大的用处。过早把它变成迭代器无疑是画蛇添足的行为。

  你觉得这样的解读合理吗?欢迎和我讨论这个话题。

  3.什么是范围类型?

  以上是我对“range()为什么不产生迭代器”的回答。顺着这个思路,我研究了它生成的range对象。我一研究就发现这个range对象也不简单。

  第一个奇怪的是,它是一个不可变的序列!我从来没有注意到这一点。虽然我从来没有想过修改range()的值,但是这个不可修改的特性还是让我很惊讶。

  翻看文档,官方明确将3354分为列表、元组、范围对象三种基本序列类型。(有三种基本的序列类型:列表、元组和范围对象。)

  我没注意到这个。原来范围类型是和链表、元组状态一样的基本序列!我一直记得字符串是不可变的序列类型,但是我从来没有想过这里有不可变的序列类型。

  范围序列和其他序列类型有什么区别?

  通用序列支持12种操作。范围序列只支持其中的10个,不支持加法拼接和乘法重复。

  图像

  那么问题来了:它也是一个不可变的序列。为什么字符串和元组支持以上两种运算,而范围序列不支持?虽然不可变序列不能直接修改,但是我们可以把它们复制到新的序列中进行操作。为什么range object连这个都不支持?

  且看公文的解释:

  …因为范围对象只能表示遵循严格模式的序列,而重复和连接通常会违反该模式。

  原因是range对象只表示遵循严格模式的序列,重复和拼接通常会破坏这种模式…

  问题的关键在于范围序列的模式。仔细想想,其实就是一个等差数列(喵,我高中数学知识没忘……),拼接两个等差数列,或者反复拼接一个等差数列。想想真的不合适,这也是range类型不支持这两种操作的原因。可以推断,其他修改动作也会破坏等差数列的结构,所以干脆不要修改。

  4.摘要

  回顾全文,我得到两个冷门的结论:range是迭代对象而不是迭代器;range对象是不可变的算术序列。

  如果只是看结论,可能感觉不到,甚至会说没什么大不了的。但如果我问,为什么range不是迭代器,为什么range是不可变序列?这两个问题还能给出一个不言自明的设计思路吗?(PS:我决定了。如果我有机会采访别人,我需要问这两个问题。哎~)

  由于range对象微妙而有趣的特性,我认为这篇文章值得一写。本文写的是迭代器的系列文章,所以对迭代器的基础知识介绍不多。另外,还有一个特殊的迭代器值得单独编写,那就是生成器。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: