当前位置: 首页 > 后端技术 > Python

Python范围函数语法和一些讨论

时间:2023-03-26 13:22:09 Python

迭代器是23种设计模式中最常用的(之一),它在Python中随处可见,我们经常使用它,但我们并不一定意识到它的存在。在我的迭代器系列中(链接见文末),我提到了至少23种生成迭代器的方法。有的方法是专门用来生成迭代器的,有的方法是“偷偷”用迭代器来解决其他问题的。在系统学习迭代器之前,我一直以为range()方法也是用来生成迭代器的,但是现在突然发现它只生成可迭代对象,而不是迭代器!(PS:Python2中的range()生成一个列表,本文基于Python3,生成一个可迭代对象。)那么,我有这样一个问题:为什么range()不生成一个迭代器?在寻找答案的过程中,我发现自己对范围类型有一些误解。因此,本文将使您全面了解range,期待与您一起学习进步。1.什么是range()?它的语法:range(start,stop[,step]);start指计数起始值,默认为0;停止是指计数结束值,但不包括停止;step为步长,默认为1,不能为0。range()方法生成一个左闭右开的整数区间。对于range()函数,有几点需要注意:(1)表示一个左闭右开区间;(2)它接收的参数必须是整数,可以是负数,不能是浮点数等其他类型;(3)是不可变序列类型,可以进行判断元素、查找元素、切片等操作,但不能修改元素;(4)是可迭代对象,但不是迭代器。2.为什么range()不产生迭代器?可以获取迭代器的内置方法有很多,比如zip()、enumerate()、map()、filter()、reversed()等,但是像range()这样的少数方法只能获取可迭代对象(如有反例请告知KAIFX返利https://www.kaifx.cn/broker/t...)。这就是我存在知识误区的地方。在for循环中遍历时,可迭代对象与迭代器具有相同的性能,即惰性求值,空间复杂度和时间复杂度没有区别。我把两者的区别总结为“一二不同”:相同的是可以惰性迭代,不同的是可迭代对象不支持自遍历(即next()方法),并且迭代器本身不支持切片(即__getitem__()方法)。尽管存在这些差异,但很难断定它们中的哪一个更优越。现在微妙的是,为什么迭代器是为五个内置方法设计的,而可迭代对象是为range()方法设计的?将它们全部统一起来不是更好吗?事实上,为了标准化,Pyhton已经做了很多这种事情。比如Python2中有range()和xrange()两个方法,Python3干掉其中一个,用的是“李代桃僵尸”的方法。为什么不更正式一点,让range()生成一个迭代器呢?关于这个问题,我没有找到官方的解释,以下纯属个人看法。zip()等方法需要接收某些可迭代对象的参数,这是一个对它们进行再处理的过程,所以他们也希望立即产生某些结果,所以Python开发者将这个结果设计成一个迭代器。这样还有一个好处,当用作参数的可迭代对象发生变化时,生成的迭代器不会因为被消耗而被错误使用。range()方法不同。它接收的参数不是可迭代对象。它是一个初始处理的过程,所以设计成一个可迭代的对象,可以直接使用,也可以用于其他再处理目的。比如zip()等方法,完全可以接受range类型的参数。pythonrange()函数创建一个整数列表,通常用于for循环。函数语法范围(start,stop[,step])参数说明:start:从start开始计数。默认是从0开始,比如range(5)等价于range(0,5);停止:计数到停止结束,但不包括停止。例如:range(0,5)是[0,1,2,3,4]没有5step:步长,默认为1。例如:range(0,5)等同于range(0,5,1)instancerange(10)#from0to10[0,1,2,3,4,5,6,7,8,9]range(1,11)#从1到11[1,2,3,4,5,6,7,8,9,10]range(0,30,5)#步长为5[0,5,10,15,20,25]range(0,10,3)#步长为3[0,3,6,9]range(0,-10,-1)#负数[0,-1,-2,-3,-4,-5,-6,-7,-8,-9]range(0)[]range(1,0)[]下面是for,循环中range的使用outrunoob每个字母:x='runoob'foriinrange(len(x)):...print(x[i])...runoobrange函数说明:range([start,]stop[,step]),根据start和stop指定的范围和step设置的步长生成一个序列。例如:范围(5)  [0,1,2,3,4]范围(1,5)  [1,2,3,4]范围(0,6,2)  [0,2,4]xrange函数说明:用法和range完全一样,不同的是生成的不是数组,而是生成器。例如:xrange(5)  xrange(5)  >>>list(xrange(5))  [0,1,2,3,4]xrange(1,5)  xrange(1,5)  >>>list(xrange(1,5))  [1,2,3,4]xrange(0,6,2)  xrange(0,6,2)  >>>list(xrange(0,6,2))  [0,2,4]从上面的例子我们可以知道,在生成大数序列的时候,使用xrange会比range性能要好很多,因为不需要开辟很大的内存空间,这两个基本都是在循环的时候用到的:foriinrange(0,100):  printiforiinxrange(0,100):  printi这两个输出结果是一样的,其实有很多不同,range会直接生成一个list对象。a=range(0,100)printtype(a)printaprinta[0],a[1]输出:[0,1,2,3,4,5,6,7,8,9、10、11、12、13、14、15、16、17、18、19、20、21、22、23、24、25、26、27、28、29、30、31、32、33、34、35、36、37、38、39、40、41、42、43、44、45、46、47、48、49、50、51、52、53、54、55、56、57、58、59、60、61、62、63、64、65、66、67、68、69、70、71、72、73、74、75、76、77、78、79、80、81、82、83、84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99]01xrange不直接生成列表,每次调用A时返回valueof:a=xrange(0,100)printtype(a)printaprinta[0],a[1]Outputresult:xrange(100)01所以xrange循环的性能比range嘛,尤其是返回量大的时候,尽量用xrange,除非你需要用range来返回一个列表。