十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
range()函数的用法如下:
站在用户的角度思考问题,与客户深入沟通,找到菏泽网站设计与菏泽网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:成都做网站、网站建设、企业官网、英文网站、手机端网站、网站推广、主机域名、雅安服务器托管、企业邮箱。业务覆盖菏泽地区。
(1)range(stop)
创建一个(0,stop)之间的整数序列,步长为1。
(2)range(start,stop)
创建一个(start,stop)之间的整数序列,步长为1。
(3)range(start,stop,step)
创建一个[start,stop)之间的整数序列,步长为step。
参数介绍:
start:表示从返回序列的起始编号,默认情况下从0开始。
stop:表示生成最多但不包括此数字的数字。
step:指的是序列中每个数字之间的差异,默认值为1。
range()是Python的内置函数,在用户需要执行特定次数的操作时使用它,表示循环的意思。内置函数range()可用于以列表的形式生成数字序列。在range()函数中最常见用法是使用for和while循环迭代序列类型(List,string等)。
简单的来说,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() 方法生成一段左闭右开的整数范围。
对于 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() 方法作为一种初级生产者,它生产的原料本身就有很大用途,早早把它变为迭代器的话,无疑是一种画蛇添足的行为。
对于这种解读,你是否觉得有道理呢?欢迎就这个话题与我探讨。
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 是不可变序列呢?对这俩问题,你是否还能答出个自圆其说的设计思想呢?(PS:我决定了,若有机会面试别人,我必要问这两个问题的嘿~)
由于 range 对象这细微而有意思的特性,我觉得这篇文章写得值了。本文是作为迭代器系列文章的一篇来写的,所以对于迭代器的基础知识介绍不多,另外,还有一种特殊的迭代器也值得单独成文,那就是生成器了。
第11题
因为取字符串TempStr的从TempStr[3]到TempStr[-2]的字符,
这里的下标都是从0开始,Python的数学取值区间都是[3,-1)半开区间,
因此取值范围是[3,-2],运行结果是3.14159
第13题
这是一个求400到500间的水仙花数的程序,水仙花数是指各个数位上的数的3次方的和等于这个数本身的3位数,
变量i是取这个3位数的百位上的数字,变量j是取这个3位数的十位上的数字,变量k是取这个3位数的个位上的数字,
如果这个数等于各个数位上的数的3次方的和,则打印这个数,在400到500中水仙花数只有407.
你也可以用4*4*4+0*0*0+7*7*7=64+0+343=407来判断答案是A,408不满足上述条件,153和159不在400到500范围内
第43题
Python中的list中的index函数是返回字符串's'在list中的索引位置(Python的索引下标都是从0开始),后面的5和10,是可选项表示查找从下标5到下标10的范围,
因为Python都是半开区间,所以实际范围为[5,9]区间,所以在"ky is"中查找's',其索引位置在整个字符串中是9,返回打印9
01 Re概览
Re模块是python的内置模块,提供了正则表达式在python中的所有用法,默认安装位置在python根目录下的Lib文件夹(如 ..\Python\Python37\Lib)。主要提供了3大类字符串操作方法:
字符查找/匹配
字符替换
字符分割
由于是面向字符串类型的模块,就不得不提到字符串编码类型。re模块中,模式串和搜索串既可以是 Unicode 字符串 (常用str类型) ,也可以是8位字节串 (bytes,2位16进制数字,例如\xe5) , 但要求二者必须是同类型字符串。
02 字符串查找/匹配
预编译:compile
在介绍查找和匹配函数前,首先需要知道re的compile函数,该函数可以将一个模式串编译成正则表达式类型,以便后续快速匹配和复用
import re pattern = re.compile(r'[a-z]{2,5}') type(pattern) #re.Pattern
此例创建了一个正则表达式式对象 (re.pattern) ,命名为pattern,用于匹配2-5位小写字母的模式串。后续在使用其他正则表达式函数时,即可使用pattern进行方法调用。
匹配:match
match函数用于从文本串的起始位置开始匹配,若匹配成功,则返回相应的匹配对象,此时可调用group()方法返回匹配结果,也可用span()方法返回匹配起止下标区间;否则返回None
import re pattern = re.compile(r'[a-z]{2,5}') text1 = 'this is a re test' res = pattern.match(text1) print(res) # if res: print(res.group()) #this print(res.span()) #(0, 4) text2 = '是的, this is a re test' print(pattern.match(text2))#None
match函数还有一个变形函数fullmatch,当且仅当模式串与文本串刚好全部匹配时,返回一个匹配对象,否则返回None
搜索:search
match只提供了从文本串起始位置匹配的结果,如果想从任意位置匹配,则可调用search方法,与match方法类似,当任意位置匹配成功,则立即返回一个匹配对象,也可调用span()方法获取起止区间、调用group方法获得匹配文本串
import re pattern = re.compile(r'\s[a-z]{2}') text1 = 'this is a re test' res = pattern.search(text1) print(res) # if res: print(res.group()) #is print(res.span()) #(4, 7) pattern2 = re.compile(r'\s[a-z]{5}') text2 = '是的,this is a re test' print(pattern2.search(text2))#None
match和search均用于匹配单个结果,唯一区别在于前者是从起始位置开始匹配,而后者从任意位置匹配,匹配成功则返回一个match对象。
全搜索:findall/finditer
几乎是最常用的正则表达式函数,用于寻找所有匹配的结果,例如在爬虫信息提取中,可非常方便地提取所有匹配字段
import re pattern = re.compile(r'\s[a-z]{2,5}') text1 = 'this is a re test' res = pattern.findall(text1) print(res) #[' is', ' re', ' test']
findall返回的是一个列表对象类型,当无匹配对象时,返回一个空列表。为了避免因同时返回大量匹配结果占用过多内存,可以调用finditer函数返回一个迭代器类型,其中每个迭代元素是一个match对象,可继续调用group和span方法获取相应结果
import re pattern = re.compile(r'\s[a-z]{2,5}') text1 = 'this is a re test' res = pattern.finditer(text1) for r in res: print(r.group()) """ is re test """
当匹配模式串较为简单或者仅需单词调用时,上述所有方法也可直接调用re类函数,而无需事先编译。此时各方法的第一个参数为模式串。
import re pattern = re.compile(r'\d{2,5}') text = 'this is re test' re.findall('[a-z]+', text) #['this', 'is', 're', 'test'] 03 字符串替换/分割
替换:sub/subn
当需要对文本串进行条件替换时,可调用re.sub实现 (当然也可先编译后再用调用实例方法) ,相应参数分别为模式串、替换格式、文本串,还可以通过增加缺省参数限定替换次数和匹配模式。通过在模式串进行分组,可实现字符串的格式化替换(类似字符串的format方法),以实现特定任务。
import re text = 'today is 2020-03-05' print(re.sub('-', '', text)) #'today is 20200305' print(re.sub('-', '', text, 1)) #'today is 202003-05' print(re.sub('(\d{4})-(\d{2})-(\d{2})', r'\2/\3/\1', text)) #'today is 03/05/2020'
re.sub的一个变形方法是re.subn,区别是返回一个2元素的元组,其中第一个元素为替换结果,第二个为替换次数
import re text = 'today is 2020-03-05' print(re.subn('-', '', text)) #('today is 20200305', 2)
分割:split
还可以调用正则表达式实现字符串的特定分割,相当于.split()方法的一个加强版,实现特定模式的分割,返回一个切割后的结果列表
import re text = 'today is a re test, what do you mind?' print(re.split(',', text)) #['today is a re test', ' what do you mind?'] 04 总结
python中的re模块提供了正则表达式的常用方法,每种方法都包括类方法调用(如re.match)或模式串的实例调用(pattern.match)2种形式
常用的匹配函数:match/fullmatch
常用的搜索函数:search/findall/finditer
常用的替换函数:sub/subn
常用的切割函数:split
还有其他很多方法,但不是很常用,具体可参考官方文档
另外,python还有第三方正则表达式库regex可供选择
到此这篇关于一文秒懂python正则表达式常用函数的文章就介绍到这了,希望大家以后多多支持!
Python range()函数可创建一个整数列表,一般用在for循环中。
注意:Python3 range()返回的是一个可迭代对象,类型是对象,而不是列表类型,所以打印的时候不会打印列表。
函数语法:
range(start,stop[,step])
参数说明:
start:计数从start开始。默认是从0开始。例如range(5)等价于range(0,5);
stop:计数到stop结束,但不包括stop。例如:range(0,5)是[0,1,2,3,4]没有5;
step:步长,默认为1。例如:range(0,5)等价于range(0,5,1)。
实例:
range(10) # 从 0 开始到 9
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
range(1, 11) # 从 1 开始到 10
[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)
[]
以下是range在for中的使用,循环出runoob的每个字母:
x = 'runoob'
for i in range(len(x)) :
... print(x[i])
...
r
u
n
o
o
b