![Python大学实用教程](https://wfqqreader-1252317822.image.myqcloud.com/cover/611/35537611/b_35537611.jpg)
3.3 字符和字符串
观察计算机的键盘,上面每个键对应着一个“字符”(character)。注意,字符不仅是字母,通常包括字母、数字、标点符号和一些控制符等。当计算机能够处理字符后,它就不再单纯“计算”了,而是具有了“电脑”的功能。
3.3.1 字符编码
如前所述,计算机只能认识二进制数字,所有提交给它的东西都要转化为二进制才能被认识。要想让计算机能够处理字符,也要如此处理。必须把字符与二进制的位(bit)之间建立起一个对应关系,这种对应关系被称为“字符编码”。
1960年代,美国发布了“美国信息交换标准代码”(American Standard Code for Information Interchange,ASCII),主要规定了英语字符在计算机中的编码。1986年发布的最新版一共规定了128个字符的编码。
利用Python中的内置函数ord可以得到ASCII中某个字符编码的十进制表示。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_53.jpg?sign=1739535501-PMAwZVI8OyLJ3vgYq77lBHradMSCSYDX-0-a766cc704bdfa67e0025ec17580c61d0)
这个十进制数字对应的二进制数字可以用bin()函数得到。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_54.jpg?sign=1739535501-UUrg2yOvd25Zmi6ikrYRVAo0qU5WkkB6-0-4ab5a48c47b30293cbd662372dd53f74)
只不过在ASCII中,每个字符的编码只占用了1字节的后7位,最前面的一位统一规定为0,即为01000001。
ASCII对于英语而言已经足够了,但英语以外的语言则不然了。比如汉字,显然不能用1字节(1字节最多可以表示256种字符,而汉字多达10万个,最常用的大约有3000~4000个),于是就要用多字节表示一个字符。比如,简体中文编码GB2312使用2字节表示一个汉字,理论上能够支持256×256=65536个字符。
除了汉语,还有好多种语言,它们都需要让计算机认识,于是就有了各种样式的编码(仅中文就有多种编码,如GB2312编码、BIG5编码、HKSCS编码、GBK编码等)。结果导致同一个二进制数字在不同编码方案中对应着不同的字符,这就是“乱码”产生的原因之一。所以,需要一个统一的编码方案。
于是Unicode应运而生。Unicode的中文翻译为:万国码、国际码、统一码、单一码,目的是实现编码方案的“世界大同”,由位于美国加州的The Unicode Consortium(统一码联盟,一个非赢利机构)负责维护。
但是,Unicode 只是一个字符集,而没有制定编码规则,所以需要再制定Unicode的实现方式(Unicode Transformation Format,UTF),于是出现了UTF-16、UTF-32等。现在使用最广泛的是UTF-8(8-bit Unicode Transformation Format),也是互联网普遍采用的Unicode实现方式。图3-3-1所示的是本书作者所用的IDE设置的编码方式。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_55.jpg?sign=1739535501-yiAoHARxAKr82v2CmmzPgNESQrXHSQZk-0-e1b2010d7cad03324dfb8c1e4017d087)
图3-3-1 IDE的编码设置
在交互模式中,还可以查看自己的计算机所使用的默认编码。下面的操作显示了作者所用计算机的编码方式。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_56.jpg?sign=1739535501-CfykPlV7L0m6SIo6pj461u7prcNqnhQv-0-17705ca8fbb56293f027e45a2b5a28e5)
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_57.jpg?sign=1739535501-q3I7wEaLvc1KniU9Sf1kqnST3UB964Rw-0-90e52d03e19418c4032f57024edeab94)
在3.2.10节中写的程序文件中,第一行“#coding:utf-8”也是声明本程序文件所采用的字符编码方式是UTF-8(与所使用编辑器编码方式保持一致)。
在Python中,不但可以使用ord函数得到每个字符的编码,而且能够使用chr函数实现反向操作。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_58.jpg?sign=1739535501-4kDvIWxZ92C70QdYgfdj6tblUHE22i5Y-0-12277d92eada2b8d933c65a76bba3455)
因为Python 3支持Unicode,所以每个汉字都对应一个编码数字。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_59.jpg?sign=1739535501-xkONTO1kE6fPFNQz7z3XkRAkqkNBniWE-0-a1b9e65ba14a125c0d89d4f2d45b4a7a)
解决了单个字符问题,就可以研究多个字符组成的“串”了。
3.3.2 认识字符串
其实,前面已经出现的“hello,world”就是一个字符串(string)。所谓字符串,在Python中就是用单引号或双引号包裹着的若干字符(见图3-3-2)。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_60.jpg?sign=1739535501-gYR6087Mz6YMrJyvpQFLanDRUhCufhs4-0-d0e62a80501fecdb0d84cc45d8827038)
图3-3-2 字符串组成部分
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_61.jpg?sign=1739535501-qvgzrwBOdIm9Dip6AelWxYg7iijPeHIs-0-6853c6c7daa9e550cd886c6af913bdd3)
字符串也是Python中的内置对象类型,用type函数查看,返回值为str,它就是字符串的类型名称。
注意,包裹字符串的单引号或者双引号是字符串的标志,在键盘输入的时候必须是英文状态,并且要成对出现。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_62.jpg?sign=1739535501-3Bh1zLhI2ml88RfPG2Dqe9VQzNTSAKZp-0-481477be50c7a91619f3c44c2a3300a8)
在引号中不仅可以放字母、汉字,还可以放其他字符,如数字。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_63.jpg?sign=1739535501-YUWvIHM4CJsOOHEeMv1EDaukkxz6NuN4-0-0d77790040231f4d1fc4cd9626f1ebe0)
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_64.jpg?sign=1739535501-tiHUyJWnOoSH9QmmF5PcRyULbdIyCe1J-0-364e63fd52165fb36b32a522810c8489)
尽管是数字,用引号包裹后,就不再是整数了,变成了字符串。这种由数字组成的字符串可以通过int函数和str函数实现相互间的类型转化。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_65.jpg?sign=1739535501-lZ5SkBEanpIKGPCb65jvZ2qPjv1z2rsf-0-572888fac83a94e8758b593250f94698)
请注意下面的写法:
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_66.jpg?sign=1739535501-bXneEL0t8Bi2xX3Dq3BeVLlgyr1IUi0p-0-d9b7c88076356d0ea77bf072143b6a4d)
出现了SyntaxError(语法错误)引导的提示,说明这里存在错误,错误的类型是SyntaxError,后面是对这种错误的解释:“invalid syntax”(无效的语法)。
在Python中,这一点是非常友好的,如果语句存在错误,就会将错误输出,供程序员参考改正。
print()是Python的一个内置函数,其作用是把参数中内容打印出来,通常显示在当前的交互模式所在的控制台。
解决上述错误的方法之一就是使用双引号和单引号的嵌套。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_67.jpg?sign=1739535501-o8VYSiNGVschKWlyz5rH3rX5OtncKS79-0-9b172082a3e2f7ec3c4f660796d86a93)
用双引号来包裹,双引号中允许出现单引号。其实,反过来,单引号中也可以包裹双引号。
此外,还有一种解决方法,那就是使用“转义符”。所谓转义,就是让某个符号不再表示原来的含义了。比如n,在字符串中就表示一个字母,这是原来的含义。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_68.jpg?sign=1739535501-lVC7BUslaYmhetu7TFhOXxCBZgWRQCtW-0-edcbc96c6d41f5fda405368f56d080de)
然而如果按照下面的方式操作之后,意思就变了。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_69.jpg?sign=1739535501-KGzbopV4z4xfAR0LbwNF3tW75HTiTVqu-0-e4259c2989092f4147498217d2ff3747)
注意观察这两句的区别,如图3-3-3所示。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_70.jpg?sign=1739535501-oDKRIFxkzOfP385PQFOdIfPPL4VbyHiH-0-f7a933c386d59f98d0b2e640ee9bb59d)
图3-3-3 转义符的作用
第二句中的符号“\”将本来是字母n的含义转换,与“\”符号一同组成了“\n”,其含义是换行,因此就出现了第二句的操作结果。
同样,可以这样来做,实现“what's your name?”的正确显示,尽管依然使用单引号包裹字符串,但不会报错了。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_71.jpg?sign=1739535501-SKkClF22lwsLA6qL2ekpP80IHJRP9yKR-0-764b39554371023969309e152abfe711)
表3-3-1中列出了Python中常用的转义字符及其说明,供应用时查阅。
表3-3-1 转义字符及其说明
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_72.jpg?sign=1739535501-vVib66cvKxLLURAQBBIXIVMe16K0itXk-0-b3a115c5e561f8fcfd43e72ffe28c89b)
建议读者在交互模式中测试上述转移符的显示效果。例如:
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_73.jpg?sign=1739535501-Lo4EhhkImnuUK0iDz9r9SQPYnxkoMyDJ-0-f4cbb9eeef8840375d9d36ca4c955f27)
用“\”实现转义是一个方便的做法,但是如果在字符串中用到了“\”符号,怎么办?比如,打印Windows中的路径。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_74.jpg?sign=1739535501-WhgqEH3tMfV5B2FVtWuxcuG7Pl1oAn1H-0-001267024d7044c4d96fce606bef183a)
这个输出结果显然不是所需要的。如何解决?可以继续使用转义符:
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_75.jpg?sign=1739535501-NLyTmzdZs67HG2fPRbh9OEnE8LF6ptTG-0-54dd00aef68bfb5164e20382613365c0)
此外,还有一种方法:
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_76.jpg?sign=1739535501-ZP0krvHlUCbDQ9gJVLGDEgs7vrNtANgQ-0-3ea40186987cd08f13c6768aeb529a1e)
状如r"c:\news",由r开头引起的字符串就是“原始字符串”,在里面放任何字符都表示该字符的原始含义。这种方法在Web开发中设置网站目录结构的时候非常有用。
【例题3-3-1】 在交互模式中,用print函数打印苏轼的词《江城子·密州出猎》,要求每句占一行。
代码示例
>>> print("江城子·密州出猎\n\n老夫聊发少年狂,\n左牵黄,\n右擎苍,\n锦帽貂裘,\n千骑卷平冈。\n为报倾城随太守,\n亲射虎,\n看孙郎。\n\n酒酣胸胆尚开张,\n鬓微霜,\n又何妨?\n持节云中,\n何日遣冯唐?\n会挽雕弓如满月,\n西北望,\n射天狼。")
江城子·密州出猎
老夫聊发少年狂,
左牵黄,
右擎苍,
锦帽貂裘,
千骑卷平冈。
为报倾城随太守,
亲射虎,
看孙郎。
酒酣胸胆尚开张,
鬓微霜,
又何妨?
持节云中,
何日遣冯唐?
会挽雕弓如满月,
西北望,
射天狼。
3.3.3 字符串基本操作
以熟悉的“hello world”字符串为例,它包括英文字母和一个空格(字符),还有一个重要特征要引起注意:这些字母和字符是按照一定顺序排列的,不是随机排的,更不能随意更换顺序。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_77.jpg?sign=1739535501-WUZuaJsvKYjP8wuauWBBUoiFEE6Fz4ig-0-3331ca88c6328830e1e6033841a309c7)
尽管a和b两个变量引用的字符串对象(当某个变量引用一个对象的时候,本书中会用那个变量来指代对象,如简称字符串a,事实上都是指变量a所引用的字符串对象)只有较小的差异,但a、b是两个不同的对象。
像字符串这样,其元素必须按照特定顺序排列的对象被称为“序列”。字符串是在本书中出现的第一种序列,在后续内容中,读者还能学习到其他序列对象。
字符串这样的序列存在着一系列共性的操作。
1.“+”:连接序列
对于数字,“+”的含义是实现两个数字相加,得到一个新的数字。对于字符串(序列),“+”的作用效果是将字符串连接起来,并得到了一个新的字符串。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_78.jpg?sign=1739535501-VdPouQrRb1hq47vwq2FcRt28x8xK5gbN-0-19895820b5112dc0395ba43e9ad96124)
注意,“+”连接的对象必须是同种类型的,否则报错。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_79.jpg?sign=1739535501-t0Tl43f0OJHQgyCDyPM42OYOgsRrE5Z6-0-8cae7b0d8bb7e5fe68f62e50d57a73d1)
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_80.jpg?sign=1739535501-CnWNXszmqg6BHzTA5AfSdPlihBc2GEHO-0-d3b346b2dc7ae62e432920baa09dabb8)
如果非要实现字符串和数字的连接,应该如何操作?
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_81.jpg?sign=1739535501-l8T1IqbY98MAmJM6FhxZEw61Cai3ARun-0-2883bf4871bed91280307860d4cd0df1)
可以使用类型转化的方式,将“+”两侧的对象转化为同种序列类型的对象。
2.“*”:重复元素
数值运算中的“*”表示的是乘法,对于字符串(序列),这个符号则表示要获得重复的元素。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_82.jpg?sign=1739535501-qG793WTzwcHeU8qHkbM8HUl8TfAXLs0o-0-ace196e2d97d5a62c79cbf20cf38dfdb)
3.len函数:求序列长度
len函数是一个内置函数,其作用是得到序列类对象的长度。
承接前面的操作,测量字符串r 的长度。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_83.jpg?sign=1739535501-lan37FCN0QX1SiahRO5GPpjg9dKXIjXF-0-5a2c09b4296d323e13c8172c735da89b)
请读者认真数一数,会发现r中包含10个英文字母,不要漏掉两个单词中间的空格,它也算一个字符,所以有11个字符,即长度为11。
可以进一步看看函数len返回值的类型。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_84.jpg?sign=1739535501-Jsp0rXE8c1ang2udAtFfKG59wdaPxgbn-0-617ce4b825dabcd9fbd360f7221c8e5b)
如果查看len函数的联机帮助文档,会发现这样的描述。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_85.jpg?sign=1739535501-JEyvingicIetwwGi059vkkPEMMNC27kb-0-d1964f65e26e484fe71db3791704d6bd)
描述中说明len函数返回的是一个容器(container)的元素数。字符串的确像一个容器,里面按照一定顺序装入了若干字符。
4.in:判断元素是否存在其中
如前所述,字符串是一个容器,“in”用于判断容器中是否存在某个元素。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_86.jpg?sign=1739535501-0ai5bY00MGrlOcU8pjMyt30YNL4xIgof-0-6a8a1df4c6b29f13426c4d07eede9a50)
返回True,说明该字符(串)在容器中,否则返回False(关于True和False,详见4.1.3节的内容)。
【例题3-3-2】 连接“Life is short.”和“You need Python.”这两个字符串,并且用print函数在控制台上打印出来,显示为两行。
代码示例
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_87.jpg?sign=1739535501-LN7o9WmknkXSEjYg62INaQXXA6Dkvpr9-0-493877f63efde97907f619b766f7a32d)
3.3.4 索引和切片
作为序列中一员的字符串,每个字符都是按照特定顺序排列的,不能随意更换位置。因此,可以给每个字符进行编号。
由此,可以把“序列”理解为“有序排列”。在Python中,给这些编号取了一个文雅的名字,叫作“索引”(index。其他编程语言也这么称呼,不是Python独有的)。
给字符串中的字符(或序列中的元素)进行编号(即索引)的方法有两种:一种是从左边开始编号,依次为0、1、2、…,直到最右边的字符结束;另一种是从右边开始,依次是-1、-2、-3、…,直到最左边的字符结束。
如图3-3-4所示,对字符串中的所有字符建立索引。特别注意,两个单词中间的那个空格也占用了一个位置,空格是一个字符。“无”不完全等于“没有”。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_88.jpg?sign=1739535501-pe2EscgksWIErVXJpiA1NvTzmizU44W8-0-599384950493f26c260a5e8edd0775f0)
图3-3-4 字符串中的索引
再有,因为可以从两个方向开始编号,所以每个字符可以有两个索引。
字符的索引建立好了,自然可以通过索引找到每个字符了。这就好比每个居民都有一个身份证号(理论上居民个人和身份证号是一对一的关系),通过身份证号(相当于索引)就能找到对应的人。在Python中,实现这种操作的方式是使用“[]”符号,如下操作:
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_89.jpg?sign=1739535501-JtwtUxi2SQQZHKo61P2DqWKVopKk4C9g-0-0aabc47c553a16e3ca17beefb496305d)
变量r引用了字符串对象,后面的“[]”中是字符的索引。操作示例显示,不论是用从左边开始计数的索引还是用从右边开始计数的索引,都能得到那个字符。
如果使用的索引超出了该字符串的索引范围,则会报错。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_90.jpg?sign=1739535501-POu4Igi5mqkQahRj84VG3q5eQbx6keSv-0-e09a9ab5a4dbcf6051f1f256044a22c6)
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_91.jpg?sign=1739535501-JOWUDpezbWFju3GyLyMpNoVpWLArG5BL-0-9687a62da0ede3febe3f2d1a38414331)
为了避免这种情况,需要提前知道最后一个字符的索引才好。一种方式是通过len函数得到字符串的字符数(长度),即可知道最大索引了。另一种方式是使用下面的方式直接得到最右边的字符的索引。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_92.jpg?sign=1739535501-3vYupsL7O9QQqEFpac4t0iKEcp4t0DI0-0-bd028620602a408be7af80843d17daa7)
index()是字符串对象的一个方法(关于对象的“方法”,请参考3.1节的简述),能够得到某字符在字符串中的索引(按照从左开始计数的索引),且是第一次出现。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_93.jpg?sign=1739535501-VbnFK1CSj3UaBXfBgWGkK5E13YMRbQyU-0-78778507c8f3ffa818e0acb0b33f1511)
通过索引,不仅可以得到某个指定字符,还能得到若干字符。操作方式如下:
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_94.jpg?sign=1739535501-tZjKJ4SvuoV9uizm3lqNdgM9iF8FmDJ9-0-aced3ade7871aedce82fb84a9cb072b4)
通过r[1:8]方式从字符串r 中“得到”了多个(不是一个)字符——称为“切片”(slice)。如图3-3-5所示,将索引是1、2、3、4、5、6、7的字符“切”出来。从结果中可以看出,结束索引8所对应的字符没有被“切”下来,这是Python中的普遍规则,简单概括为:前包括,后不包括。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_95.jpg?sign=1739535501-6MRy0mze5u4n9sislVFvm6SPZwu41VWH-0-09d5b2f36c74c069d86111ef8f029d21)
图3-3-5 字符串切片
原字符串被“切”出了一部分,但并没有因此而破坏原字符串。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_96.jpg?sign=1739535501-EfrZMCtu2F3KF2qtPvRYgLKqdyOGFdkC-0-a2fb62610c814f46eb212ed882db49f1)
这说明“切片”是比照着索引在原字符串中所对应的字符,重新创建了一个字符串对象。从最终结果看,貌似是从原字符串上“切下来的一部分”。
如果用一个普遍的表达式来说明切片操作的方式,可以表示为:
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_97.jpg?sign=1739535501-UA7Mm83Sx2yTsfVzVPDoGyyaatRaYLuX-0-8f812dcc66ede0a2bfb0f89cf0bf2834)
❖ indexstart:表示开始的索引。如果是从第一个字符开始,可以省略。
❖ indexstop:表示结束的索引(切片中不含此索引对应的字符)。如果是到最后一个字符结束(含最后一个),可以省略。
❖ step:表示步长,默认为1;可为正整数,也可为负整数。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_98.jpg?sign=1739535501-1t233H19yrxndfcq3rBA2P9JCVzz3sF5-0-e22d28b816712beabad7d6619848550c)
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_99.jpg?sign=1739535501-vDvKPr1WgnFnOdAej4GZdBEwiskR8XVJ-0-98e9cce888e8377bde4d8b99eb787422)
省略indexstart索引,表示切片以字符串的开始为开始。对照图3-3-5可知,索引8和-3对应的是同一个字符(作为结束字符,不包含在切片中),所以上述两种操作结果一样。
同理,如果省略indexstop,则表示到字符串结束,即切片中的字符直到原字符串最后一个字符为止,并包含最后一个字符。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_100.jpg?sign=1739535501-JlghjzMlgUMJ7L1rRYXHUiErpF9nIkke-0-8022565dd60c373da0052f308b76bf8b)
以上操作中,步长都省略,即:使用了步长的默认值1。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_101.jpg?sign=1739535501-m4r8sbB7R1amTNG6sffqmxu6wu5DvnCL-0-00ac52c63d0c037009e6be077474f8ec)
r[1:]和r[1::1]的操作结果是一样的。但是,如果设置步长不是1,则会按照步长切片。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_102.jpg?sign=1739535501-4yRIQYtlufvaVkegUVXzWZt2UP1H94yz-0-e19245120c84e78c4251a10bb8f91129)
请读者通过操作比较r[:8]和r[0:8],以及r[1:]和r[1:10]的结果,结合前面的内容给予理解。
在r[1::1]和r[::2]操作中,步长分别为1和2,都是正整数。前面介绍步长的时候特别提到,它也可以为负整数。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_103.jpg?sign=1739535501-6qbboN9dswhN80JPTRWwAGacbsgP8osn-0-812cc8c1d5f91c2bc4f16d1a467c72bc)
r[::-1]中的步长为负数,结果得到了原字符串的反转。
这个反转是如何得到的呢?先要理解步长(step)“正负”含义。当步长为正整数时,相当于“站在”了字符串的左侧“看”字符串中的每个字符(见图3-3-6)。先看到的字符所对应的索引就是indexstart,后看到的字符所对应的索引就是indexstop。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_104.jpg?sign=1739535501-jzQhHdfYFHQihmqcsNHtvsqrAtziyoTd-0-41d0e45f01a8fbcf02036ef67e48da69)
图3-3-6 步长为正整数
注意,索引不区分是从左边开始计数,还是从右边开始计数,如下述操作的结果都一样。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_105.jpg?sign=1739535501-3NFCPlT3fTW3uJ20UE0bG11mKXO4yRnx-0-2c1eb81162cd8ebb7d952274db0f3c26)
当切片步长为负整数的时候,与上述不同的是调整了“看”列表的位置(见图3-3-7),改为“站在右侧看”,其他原则不变,即:依然是先看到的字符对应的索引是indexstart,后看到的字符对应的索引是indexstop。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_106.jpg?sign=1739535501-qgCkVX2wCb67QBSwMfpXGImMRTeg1CIk-0-2a24e0d0e15d2d15575e5e654caf1bcb)
图3-3-7 步长为负整数
以下各项操作同样等效。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_107.jpg?sign=1739535501-iJghr6jLJiwqq7vw7Q29fQqm2M570XKP-0-8ead8859b25aedd6179c4090e61515d6)
理解了上述切片原则后,再看r[::-1]就不难理解了。步长为-1,即为“站在右侧看”,从“看到”的第一个字符开始(r[-1]对应的字符),到最后即最左侧的字符(r[0]对应的字符),并包括最后一个为止。因此得到了一个相对于原来的反转的字符串。
此处以字符串为例介绍了切片的基本方法,这种方法适用于所有序列类型的对象。
【例题3-3-3】 对字符串“123456789”,通过切片操作得到如下结果:
❖ 得到“2468”。
❖ 得到“1234”。
❖ 得到“963”。
❖ 得到“69”。
❖ 得到“987654321”。
代码示例
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_108.jpg?sign=1739535501-aM5E1nb8sdHxuSBD98fP7O97Fs3U50Cn-0-da4a70069159ba25f90c0aeb629c39a9)
3.3.5 键盘输入
计算机(“电脑”可能更形象)的智能,一种体现就是可以接收用户通过键盘输入的内容。Python提供了内置函数input,用于接收用户通过键盘输入的信息。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_109.jpg?sign=1739535501-8Ul9adgODdZeqBDcZYCH2G1RwOwqhpLG-0-10b5dac53acdf55d1b15bab363b4c8ae)
从联机帮助文档中已经清晰地看到了input 函数的使用方法,下面在交互模式中操练此函数。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_110.jpg?sign=1739535501-wpp2Z5fMFrLQCDXTtCkgyorSwdymZSUo-0-c9f77e86897364c6baece3f78f48fb97)
如上述操作,通过键盘输入“python”后,回车,将所输入的内容作为返回值呈现。
从帮助文档中可知,input 函数的返回值是一个字符串类型的对象,于是使用下述方式,用变量引用此返回值对象。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_111.jpg?sign=1739535501-kxVXRImcV24j6yHUdwllzRi7wdDBIxKM-0-21ffe750f5edde8f25e286f2f8866f9c)
不论通过键盘输入什么字符,input函数的返回值都是字符串。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_112.jpg?sign=1739535501-2usabo9ZsoDvCzcRj82PC2J4lBEoCRm0-0-87929b5fe1fc365370644a0e15317007)
有了以上两个准备,接下来就可以写一个能够“对话”的小程序了。
【例题3-3-4】 编写一段程序,实现如下功能:
(1)询问姓名和年龄。
(2)计算10年之后的年龄。
(3)打印出所输入的姓名和当前年龄、10年之后的年龄。
代码示例
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_113.jpg?sign=1739535501-WELCzRYInRCbwOR14kvBdj2MfofbKJDl-0-3b180ad408b6f6257b5448db57610a77)
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_114.jpg?sign=1739535501-4yvbSbrJGGvfQEnvIUcfPYVoVnFtlr72-0-e8cd0f95fc7dff74064b74c575f0acaf)
在本程序中需要注意的是类型转化。①中的变量age引用的是一个字符串类型的对象,这个对象必须转化为整数类型之后才能参与②中的运算,所以在②中使用了int(age)。而当一个整数与字符串通过“+”连接的时候,又需要转化为字符串类型,③中的str函数即此意图。
请读者自行调试这个程序,如果遇到了报错,请认真看报错信息,从中找到修改的方向。
上述代码示例并非十分完美,只是局限于本书已经讲述过的知识实现了一些基本功能。关于字符串的更多内容,还有待于深入学习它的更多方法。
3.3.6 字符串的方法
字符串是对象类型,也是对象,因此它会有一些方法供开发者使用,而且这些方法已经内置好了——内置对象,必须如此。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_115.jpg?sign=1739535501-tKNdmYprIdj7JZAo3IZWKoQpCqdvnSnq-0-5a6f0bea9aaf82cfb6f9107a94da954b)
通过dir(str)看到了字符串对象的所有属性和方法,可以粗略地划分为两类:一类是名称以双下滑线开始和结尾的,称为“特殊方法”和“特殊属性”;另一类是用看起来很普通的名称,如capitalize等,笼统称为“方法”和“属性”。
对于内置对象的方法而言,因为调用的时候类似使用函数,所以也有资料称之为某对象的函数。本书按照对象的方法来称呼。在后续学习中,我们会区分函数和方法的含义。
字符串有那么多方法,这里不会一一介绍,仅选几个,用以示例如何通过联机帮助文档学习其使用方法。
在3.3.4节提到过一个名为index()的方法,使用它可以得到字符串中某个字符的索引。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_116.jpg?sign=1739535501-veu9d1aUUevHYnJzVK2pBknUxwBwtbaV-0-111d5afb7bd87ba612bf881e068d39b9)
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_117.jpg?sign=1739535501-kJ4W7jyaz31wKKFkh2cQQY4bQL0WHyDc-0-bd95c374b65d8cc3c04206369d14de8b)
以字符串中的index()方法为例,解读帮助文档的含义,理解如何使用它。如图3-3-8所示,根据图中所标识的各项建议,在交互模式中进行适当练习,从而理解各项含义。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_118.jpg?sign=1739535501-D6AO76vIFtSsoJsKTRcERKNC7bXJFoA4-0-3cf95bcd1f615e09b33e42d180ea6d23)
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_119.jpg?sign=1739535501-KvW9PGbfdaHDpduEv3oxPLINIivmFaOS-0-1fbb0b150f08727d16943a106a8d7740)
图3-3-8 分解index方法
没有规定查找的索引范围,即没有给start和end参数传值,则默认为在整个字符串的范围查找,并且返回找到的第一个子字符串的索引。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_120.jpg?sign=1739535501-t8HxNwA1c2XVnHvsfGH6Ov6U1fcXydb2-0-3333d0f29bbbbc96898bc8b587a84bb5)
指定了开始查找的索引,即start=20,于是从这个位置开始向后查找,并且返回在这个范围内所找到的第一个子字符串的索引。
更准确的理解还依赖于读者认真阅读帮助文档中的说明。
后续的内容中,本书不再呈现帮助文档,但不意味着这种方法不重要,而是相当重要,只是受到篇幅的限制,并且查看文档的方法也不难。
1.“is”开头的方法
仔细观察dir(str)的结果,其中有若干以“is”作为名称开始的方法。这些方法无一例外,都是返回了bool类型。这种类型对象会在4.1.3节中详述,中文为“布尔”类型,只有True和False两个值。例如:
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_121.jpg?sign=1739535501-5xEv1tytXJh9U7Tvqj0Z5y2UOturkD8k-0-f1530c3adba6c085b80e99987f176e0e)
字符串的isdigit()方法是用来判断当前字符串对象是否完全由数字字符(即键盘上的1、2、3、4、5、6、7、8、9、0)组成。如果是,则返回True,否则返回False。
其他若干类似的方法,基本操作和结构都与上述示例类似,请读者逐一查看联机文档的说明,并在交互模式中进行调试。
2.分隔和组合
字符串对象提供了根据某个符号分割字符串内容的方法split()。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_122.jpg?sign=1739535501-l5zuzU6Ok91S65qSwkmjUnWVRwW7KMNb-0-d981ebd1f7e8a09de0d6c57168f1afb7)
这是用空格作为分割符,得到了一个列表(List)类型的返回值(详见3.4节)。
帮助文档中对分隔符做了说明,请认真阅读。特别注意,如果没有指定特定的分隔符,Python会默认空格为分隔符。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_123.jpg?sign=1739535501-dtS1VPkWzNVVsqLT3iEkD7wjoUduPuf1-0-a6fe59c154bc31ef1bda1f55e2430d1a)
注意比较上面三种不同的情况。
除了可以依据某个字符对字符串进行划分,还可以用某个字符把另一种对象组合成为一个字符串,这个过程有点类似split()方法的逆向过程,使用的是字符串的join()方法。
如果读者查看联机帮助文档,会看到“S.join(iterable) -> str”(特别建议认真阅读帮助文档的内容),这个方法的参数中出现了“iterable”,其含义为“可迭代的”。这是某些对象所具有的特征,包括字符串在内的一些对象,被称为可迭代对象(关于“可迭代的”和“可迭代对象”详见6.10节)。通过字符串的split()方法得到的名为列表的对象,就是具有“可迭代的”特点的对象,因此下面演示就使用这个对象。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_124.jpg?sign=1739535501-QFll3dNUsduCpJkotL31Bv6BHBcqvxjp-0-012b95c3ba8a4efdb65359b8c2d89734)
③中使用了字符串"-"的方法join(),参数是前面得到的列表lst,意图是要用“-”符号把列表lst中的元素连接起来,并且返回一个大字符串。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_125.jpg?sign=1739535501-SOVEyQyFDUueLO669y9S5FwY579stfbd-0-9b51d002aa2f7db1a1b269dae29d4c20)
刚才提到字符串也是“可迭代的”,所以join()方法的参数也可以用字符串。只不过字符串的元素是字符,所以,如果用空格——也是字符——的join()方法的话,得到的结果就是④所返回的那样,每个字符之间有了一个空格。
字符串的方法众多,本书仅选几个作为示例,在后续内容中也会不断用到其他方法。读者要通过本例掌握查看文档的方法。
【例题3-3-5】 有的字符串两边有空格,或者一边有空格,用字符串中的方法,将这些空格去掉。
代码示例
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_126.jpg?sign=1739535501-NDhCGW46vlX1zO542yid0bRAeQQmqcjC-0-516e5f4c6297384f35c0252d554e9490)
3.3.7 字符串格式化输出
在字符串的诸多方法中有一个名为format的方法,下面就用它来实现“格式化输出”。
要了解这个方法的使用,还是要查看其文档,请读者自行完成。下面列举几种使用format()方法进行格式化输出的方式。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_127.jpg?sign=1739535501-zb3Ma4SAVVXsiSBLOg8EIcoLXq5hm8Fz-0-72b6b67b04b0357d8b8a3bbab8783a6e)
在交互模式中,输入了字符串"I like{0}and{1}",其中用{0}和{1}占据了两个位置,它们就是占位符。format("python","physics")是字符串格式化输出的方法,传入了两个字符串。第一个字符串“python”对应占位符{0};第二个字符串“physics”对应占位符{1},即占位符中的数字,就是参数format()方法的参数列表的顺序号(见图3-3-9)。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_128.jpg?sign=1739535501-a4iREZL89cJNn5rnqT08YctnfYIswqSl-0-6ad10a5f8365190de653b72bbf7173f4)
图3-3-9 format()方法使用解析
为了进一步理解占位符中的数字的含义,可以做如下操作。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_129.jpg?sign=1739535501-ZtUVMe8SrMoiD9kYjFUcsup2lEViUe6V-0-b636f92f0998b8f5f1c1a4e20f13013e)
既然format()实现的是“格式化”输出,就应该可以指定某种“格式”,让输出的结果符合指定的样式。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_130.jpg?sign=1739535501-DbxPQAI1QEnYmwmT6vdGchJ6xEoNaxp9-0-a392acb3d950b742929df345429d8d4f)
{0:10}表示该位置有10个字符,并且放在这个位置的字符是左对齐;{1:>15}表示该位置有15个字符,并且放在这个位置的字符是右对齐;{0:^10}和{1:^15}则表示字符串在该位置的对齐方式是居中。
除了规定字符串的对齐方式,还可以限制显示的字符个数。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_131.jpg?sign=1739535501-72Fwo3YxqzaYUademGwiTUtyAZwj0jfo-0-691ad2e0ab55852c3382c773d4d92cae)
{0:.2}中的“.2”表示对于传入的字符串,截取前两个字符。需要注意,在“:”后面和“.”前面没有任何数字,意思是该位置的长度自动适应即将放到该位置的字符串。
{1:^15.3}中的“15.3”表示该位置的长度是15个字符,但即将放入该位置的字符串应该仅有3个字符,也就是要从传入的字符串"physics"中截取前3个字符,即"phy"。
format()中,除了能够传入字符串,还可以传入数字(包括整数和浮点数),而且有各种花样。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_132.jpg?sign=1739535501-HuMjHpnNISeZW9iXi6ujpnMnLI2JonW9-0-c8e20bab1c0c9eeedbf29b7cf04d597b)
{0:d}表示在该位置放第一个参数,且为整数;{1:f}表示该位置放第二个参数,且为浮点数,此处浮点数的小数位数是默认的。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_133.jpg?sign=1739535501-D9xfp8428roKgyglqD7dab3YVwuuAEDu-0-3e350cc4bf1a3585299969086ac87962)
用{0:4d}设置此位置的长度是4个字符,并且在其中应该放置整数,在默认状态下,整数是右对齐;{1:.1f}表示该位置的浮点数小数位数为1位,并且自动采用四舍五入方式对参数中小数进行位数截取操作,默认也是右对齐。
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_134.jpg?sign=1739535501-aK1Q9ofqUz2FHxqFiLCNVgytKy8kzYHO-0-15d8e91cc1d6ff611be0e433e902cae6)
其中,{0:04d}和{1:06.1f}表示在该位置的空位用0填充。
使用字符串的format()方法进行格式化输出,实现的方式多种多样,除了上述演示,还可以这样做:
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_135.jpg?sign=1739535501-ESzJfl2lH33uciqtW5xVgKzr9g2VUcse-0-1f3ccccb9dc97f9c97caccbba5a973e2)
【例题3-3-6】 字符串有format方法,内置函数中也有format方法。用示例说明内置函数format()的使用方法。
代码示例
![img](https://epubservercos.yuewen.com/451E29/18978713308549606/epubprivate/OEBPS/Images/txt003_136.jpg?sign=1739535501-7xq8jDvowwZaA1K7L8AsQ5ze6EiWdsbC-0-e87f2ec8e757a5bde0f5520beb23c11d)