python range函数作用,python中range()函数的用法,Python中range函数的基本用法完全解读

python range函数作用,python中range()函数的用法,Python中range函数的基本用法完全解读

大多数range函数经常出现在for循环中,可以在for循环中用作索引。下面这篇文章主要介绍Python中range函数的基本用法,通过示例代码非常详细的介绍。有需要的朋友可以参考一下。

目录

前言1。什么是range()?2.为什么range()不产生迭代器?3.什么是范围类型?4.总结附件:Python的range()函数的历史总结

前言

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

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

所以,我有这个问题:为什么range()不生成迭代器?在寻找答案的过程中,我发现自己对值域的类型有一些误解。所以这篇文章会让你对range有一个全面的了解,期待和你一起学习进步。

1、range() 是什么?

其语法:range (start,stop [,step]);Start是指计数的起始值,默认为0;Stop是指计数结束值,但不包括stop;Step是步长,默认为1,不能为0。range()方法生成一个左闭右开的整数范围。

A=范围(5) #即范围(0,5)

a

范围(0,5)

镜头(a)

对于a中的x:

print(x,end=' ')

0 1 2 3 4

对于range()函数,有几点需要注意:(1)它代表左闭右开区间;(2)它接收的参数必须是整数、负数,但不能是浮点数等类型;(3)是不可变的序列类型,可以判断元素、查找元素、切片元素等。但不能修改元素;(4)它是迭代对象,但不是迭代器。

# (1)左侧关闭,右侧打开

对于范围(3,6)内的I:

print(i,end=' ')

3 4 5

# (2)参数类型

对于范围(-8,-2,2)内的I:

print(i,end=' ')

-8 -6 -4

范围(2.2)

-

类型错误回溯(最近一次调用)

.

type error:“float”对象不能解释为整数

# (3)顺序操作

b=范围(1,10)

b[0]

一个

b[:-3]

范围(1,7)

b[0]=2

类型错误回溯(最近一次调用)

.

type error:“range”对象不支持项分配

# (4)不是迭代器

hasattr(范围(3),' __iter__ ')

真实的

hasattr(range(3),' __next__ ')

错误的

hasattr(iter(range(3)),' __next__ ')

真实的

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类型的参数。

对于zip中的I(范围(1,6,2),范围(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.)

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

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

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

范围(2)范围(3)

-

类型错误回溯(最近一次调用)

.

TypeError:不支持的操作数类型:“range”和“range”

范围(2)*2

-

类型错误回溯(最近一次调用)

.

TypeError:不支持*:“range”和“int”的操作数类型

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

且看公文的解释:

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

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

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

4、小结

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

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

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

附:Python的range()函数的历史

虽然Python 2中的range()和Python 3中的range()可能共用一个名字,但它们是完全不同的动物。实际上,Python 3中的range()只是Python 2中名为xrange的函数的重命名版本。

最初,range()和xrange()都生成可以被for循环遍历的数字,但是前者一次生成所有这些数字的列表,而后者懒洋洋地生成数字,这意味着在需要时一次返回一个数字。

挂一个巨大的列表要占用内存,所以xrange()代替range()、name和一切也就不足为奇了。你可以在PEP 3100中阅读更多关于这个决定和xrange() vs range()的背景。

注意:PEP代表Python增强提案。Pep是一个涵盖广泛主题的文档,包括建议的新功能、风格、治理和理念。

有很多。PEP 1解释了它们是如何工作的,是一个很好的起点。

总结

关于Python中range函数的基本用法,本文到此结束。有关Python中range函数用法的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望你以后能支持我们!

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

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