![Python+Excel办公自动化一本通](https://wfqqreader-1252317822.image.myqcloud.com/cover/221/40795221/b_40795221.jpg)
2.4 字符串
字符串是Python中常用的数据类型,在Python 3中字符串采用的是Unicode编码,也就是任何一个字符都用2字节表示。在Python中用单引号“'”或双引号“"”来创建字符串,如下所示:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/051-2.jpg?sign=1738872554-jpdRBqxfW8E6PMwKt80wtezoCtdVS1eq-0-63f918fcb1c7d830eafe272ed3489169)
由此可见,在Python中创建字符串并不是太难。只是在其他的语言中,很多开发者都喜欢使用str作为字符串变量的标识。而在Python中str是一个内置的函数名,所以就不能使用这个标识。此外,还可以将其他数据类型转变为字符串类型,具体如下:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/051-3.jpg?sign=1738872554-uk8uI8mxZO0J2DXOzoaOHS1TqeIDax7S-0-3d9d2c33477800d1f556685254aa1c14)
运行上述代码得到的输出结果如下:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/051-4.jpg?sign=1738872554-UdUJr9o5EcEv2dEqpVR830XnobzAchqC-0-ecdc2e42cbad1aac9070db1303faba70)
由此可见,变量a_str是一个字符串,而不是数字。当使用str作为变量标识时,就会覆盖str函数,如下所示:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/051-5.jpg?sign=1738872554-07S5pcseRJOsG9u0fP0oXVFjD1xDXMkK-0-ecbbb917a0b79b317f2d95666bb18e7d)
运行上述代码得到的输出结果如下:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/052-1.jpg?sign=1738872554-Sj4LfGBOIyT8gNHrVTigEBZoPCsKXTFx-0-b7a8ac390fdb958a05f46c77043402e0)
由此可见,上下文已经不能再识别str函数,因此需要记住不要使用str作为字符串变量的标识。
说明 在Python中只有数据类型字符串,没有字符数据类型。
在C/C++和Java中存在字符串和字符的数据类型,其中字符类型使用单引号,并且只能是一个字符。而在Python中,没有字符类型,只有字符串类型,哪怕使用单引号且只有一个字符,也是字符串,如下所示:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/052-2.jpg?sign=1738872554-mYu9EoK8oXbj3fDUHTdnXPTGvGzmnD1X-0-f0b574cfb162300ddb2e43f814b7a859)
运行上述代码得到的输出结果如下:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/052-3.jpg?sign=1738872554-vyhKeWz0WpqESYZ1FlV8a7M6Q0IWcQPX-0-86b31369a97651874ad9f8fb424000d0)
由此可见,'a'是一个字符串,而不是一个字符。
2.4.1 截取子串
所谓子串是指一个字符串所包含的子集,如“人生”、“P”和“Python”都可以看成“人生苦短,我用Python”的子串。在Python中,可以通过“[]”和下标来截取字符串的子串,并且下标是以0开始的,下面通过代码清单2-16举例说明。
代码清单2-16:截取子串
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/052-4.jpg?sign=1738872554-TgGsrZOhjZDmPwFzMGxgl3MexiCfxFps-0-64dfaa6dd89ae150967fff5818c52024)
这里首先使用了len函数,这样就会返回字符串的长度。需要注意的是“[]”中不同的参数表达。例如,s[2]表示取第3个字符作为子串;s[:4]表示截取前4个字符作为子串;s[5: ]表示截取下标为5(含)之后的字符作为子串;s[7: len(s)]表示截取下标为7到len(s)的子串,此时包含下标7,但是不包含下标len(s)。运行上述代码得到的输出结果如下:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/053-1.jpg?sign=1738872554-1MStISaof3YFGj50PXuht4hTeoV96D1t-0-8675b0b45db4eb826ec3b79c9c04991f)
说明 当截取字符串使用的下标不合理时会如何?
在上述例子中采用的是合理的下标,所以可以正确截取字符串。但是,如果下标不合理又会如何?例如,截取子串s[8:2]会返回什么呢?在Python中如果遇到不合理的下标,它就会返回''。下面在代码清单2-18的基础上增加如下几行代码进行测试:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/053-2.jpg?sign=1738872554-O3WGCGAYcEV2e8xmTu3Ha1zSkGvrzvmu-0-a35615969943c895685f88000cce5952)
运行上述代码得到的输出结果如下:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/053-3.jpg?sign=1738872554-654LijPXVq2jYGHRTc0JQMTMISNohWJe-0-8bd9a8f5beb8434afb3f0586375a72dc)
由此可见,当下标不合理时,它就会返回''。
实际上,在Python中除了可以使用0到len(s)表示字符串的下标,还可以使用负数来表示反向下标,在使用负数时,最后一个字符的下标为-1,而第一个字符的下标为-len(s),如图2-3所示。
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/053-4.jpg?sign=1738872554-5L1qo7WdazsFrB2XR4AvKFeaBMnjBtkg-0-c242aa1547a30fc637573463573b3f5d)
图2-3 字符串下标图示(len(s)=13)
下面通过负数下标来截取子串,如代码清单2-17所示。
代码清单2-17:通过负数下标来截取子串
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/053-5.jpg?sign=1738872554-YVLlsFGdObWYzfyC8LQtqS9fNpWDvgKX-0-04aae8a7c35e0dbc2ac271ee1f1c0ef1)
一般来说,在使用负数下标时需要先用len函数求出它的第一个字符的负数下标值,如代码中的-1*length就是字符串第一个字符的负数下标。然后通过减法来截取字符串,这样有利于提高代码的可读性。
注意 防止下标越界
在字符串中使用下标需要防止下标越界。如果发生越界,就会在运行过程中产生错误,如下所示:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/054-2.jpg?sign=1738872554-UiT89jISRNsXaQt89oJiGFA1Q1vnmHAx-0-3de708900874cc3eb6bb119fcb5fa703)
这里的下标13和-14都已经超越了字符串的下标区间[0, 13)和[-13, 0),因此在运行时就会产生错误,输出如下结果:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/054-3.jpg?sign=1738872554-BQT6RF0JXlTUHOQk2OcQxhuTEP0X8HI8-0-da7d07d6ead1b3a7631c6e178e12f0f5)
为了防止下标越界,笔者先求出字符串的长度(length),然后根据长度控制来访问,如下所示:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/054-4.jpg?sign=1738872554-Vp4AdeNVKCpU3zU0xIe6Fw7eTfmXcUCm-0-f389cbcc2aff848c4701cf1ad566fd16)
上述代码先求出字符串的长度,然后保证下标在区间[0, length)或[-1*length, 0)访问字符串,就能够避免下标越界,这是开发者常用的技巧,而使用length作为变量名称,代码的可读性也会有所提高。
2.4.2 字符串的运算
在Python中,字符串本身也提供了许多运算功能,包括字符串连接、截取子串、判断是否为子串等。假设s="人生苦短,我用Python",下面通过表2-9来展示字符串的运算。
表2-9 字符串的运算
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/054-5.jpg?sign=1738872554-7Q0YgmR9PpWyTNZmELoc8aSCyAnxRivp-0-f840585092f8d6f36d38d11e75602206)
下面通过代码清单2-18来学习表2-9中的内容。
代码清单2-18:字符串的运算
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/055-1.jpg?sign=1738872554-AIRQjqoaOtuh9HhuCkuWhqsqIVfdMzMo-0-063f710dd6d65c0c65f2a4031e5cddfb)
需要注意最后的字符串连接数字,由于直接连接数字会发生异常,因此需要通过str函数将数字先转换为字符串才能进行连接。运行上述代码得到的输出结果如下:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/055-2.jpg?sign=1738872554-K2cHhUMkaR9ZHHPhRCr10faGD1BUumgI-0-f21349cb0931b4b4c7888d0008b2f2f4)
2.4.3 字符串的格式化
为了连接字符串,经常需要使用连接符“+”,而有时过多的字符串会使可读性大大降低,如下所示:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/055-3.jpg?sign=1738872554-wCoo8kyA7ZwMAcF7HKStNDEcOw4LJRqw-0-a59956c48dea5bbaeb77a6d7f8cfdfc9)
显然,字符串output的可读性大大降低。这个时候可以考虑使用格式化的字符串来处理,在Python中可以使用“%”来格式化字符串,然后根据数据类型在字符串中使用不同的格式化符号,如可以使用以下代码来提高代码的可读性:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/056-1.jpg?sign=1738872554-4nOV1YW4cTdm3QvosMbxlwsPpTV9TcBf-0-b02b44371a16905b8fdaf5640dee9ae7)
需要注意的是代码①中加粗的3个占位符,即“%s”、“%d”和“%.2f”。其中,“%s”表示一个字符串占位;“%d”表示一个数字占位;而“%.2f”表示浮点数占位,且精度保留2位小数。然后在字符串后面使用“%(参数列表)”的方式进行格式化,这样就可以通过参数来格式化字符串。此外,Python中还存在很多占位符,下面通过表2-10进行说明。
表2-10 字符串占位符
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/056-2.jpg?sign=1738872554-jnYENE8zhl0Pr9rGtkUNanetalJ1xb6K-0-a3c830bd64fdf9083f8bc6d86b966372)
上面只是简单的格式化,功能还不够强大。为了增强格式化的功能,在Python 2.6版本之后,Python中还提供了字符串的format函数,用来增强格式化的功能,所以在新的版本中,Python官方建议使用format函数来格式化字符串,而不是使用“%”来格式化字符串。下面通过举例来说明format函数的使用方法,如代码清单2-19所示。
代码清单2-19:使用format函数格式化字符串
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/056-3.jpg?sign=1738872554-puN1vZ9kqBNycwJWKV2sQT0gutj2A0Bd-0-d02815a481753031ca2a576edc4bccaa)
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/057-1.jpg?sign=1738872554-QIQzSw4t8kMcqg44Pj4LITI6kq4D2eEg-0-c38bf84c23de00ad85191a57e8d33c02)
在代码①处、代码②和代码③处使用了换行符“\”,所以可以另起一行来编写format函数。在代码①处,通过指定参数位置(从0开始)来格式化字符串,而“:”后可以指定参数的数据类型并格式化,这样就可以通过参数的顺序来格式化字符串。在代码②处和代码③处使用了字典,在代码②处需要指定参数位置和字典的key;而在代码③处只需要指定字典的key,只是format函数的参数写作“**params”。使用字典可以让参数占位通过名称表达具体的含义,因此具备更高的可读性,并且不存在参数顺序的限制。
说明 再次强调可读性
在代码清单2-19中,代码②处和代码③处都可以使用字典作为参数进行格式化,显然后一种方式的可读性更高,因此笔者建议使用后一种方式进行编码。
2.4.4 Python转义字符
在计算机中还存在一些特殊的字符,如常见的换行符,在Python中约定使用"\n"来表示换行,除此之外,还规定了许多特殊的字符,它们都以反斜杠“\”开头。转义字符如表2-11所示。
表2-11 转义字符
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/057-2.jpg?sign=1738872554-i9DLfhebud5bmrvIscfAIw6de5p6GWI0-0-d68a9047eb689a2d1bab21e8755a93c6)
在表2-11中,加粗的行在开发中经常用到,其他字符用得比较少,所以重点掌握常用的转义字符即可。当然,也可以取消转义字符,如下所示:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/058-2.jpg?sign=1738872554-xOJlh8avF3UwTcHBU8QszEanNhHvATgy-0-d3354f125079c73b6d6a73febc20c96c)
需要注意的是,字符串前的字符r(或R)表示字符串将不再进行转义。下面通过代码清单2-20来介绍这些常见的转义字符。
代码清单2-20:使用常见的转义字符
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/058-3.jpg?sign=1738872554-G2zfmRW2dmdAyMnr13ytcikqefW9TpAF-0-8302969d00684fabfdae3d79d201b396)
运行上述代码得到的输出结果如下:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/058-4.jpg?sign=1738872554-9K3nK4JoBP5n7YD48QTF7a49UfCoOo3t-0-6cca9a62a0b0be7eeb5b2541c69349ad)
此外,Python在多行中还提供了三引号(既可以是单引号,也可以是双引号)的编写,三引号让开发者从引号和换行等格式化的泥潭中解脱出来,它采取多行字符串所见即所得的方式来简化程序员的工作,如代码清单2-21所示。
代码清单2-21:三引号的使用
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/058-5.jpg?sign=1738872554-BPEbHVrD3r7RK4qK4vhj8x21ji5C0Y44-0-986966ba9c021e6ec32e69ed0b02c2a7)
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/059-1.jpg?sign=1738872554-qT0gJSwx5T30ZNM2ueyIti0bkCZkNV6B-0-f1d8d3741d70adf9b312c038f2b4884e)
运行上述代码得到的输出结果如下:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/059-2.jpg?sign=1738872554-QvIow7OasrQxb1n67SZdjktmCodQimri-0-9d81736d788d6a949a70b47aff5be24a)
2.4.5 字符串常用的函数
除了上述内容,Python的字符串还存在几十种方法可以对字符串进行操作,只是罗列它们非常枯燥,并且很多方法并不常用,所以本节只用代码清单2-22介绍常用的函数。
代码清单2-22:字符串中的常用函数
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/059-3.jpg?sign=1738872554-ILocI7hnUZN4OvTtmlTAAOL7OaIYduWo-0-2acbc55b062d1db2a902da9945d969b8)
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/060-1.jpg?sign=1738872554-HYjKTLWibwqnW8GfYDfxszzaJsDITvso-0-5f1827a4370d9c785c03148cb83d9a15)
以上就是字符串常用的函数,代码中也给出了清晰的注释。
在Python 3.9及其之后的版本中还加入了两个新的函数,即removeprefix和removesuffix,它们的作用是删除指定的前缀和后缀,如下所示:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/060-2.jpg?sign=1738872554-YawVJLVHGcBnzNATRHL37h7gYHWRvpr4-0-61f013895173d520556174fbc9101895)
运行结果如下:
![](https://epubservercos.yuewen.com/569A18/21190709001167706/epubprivate/OEBPS/Images/060-3.jpg?sign=1738872554-27rQv8HA6QrkbhVZhgAUk0W5AQFpBStD-0-d03b18af4299273dd35b5fb85c65d3bf)
由此可见,对应的前缀和后缀被删除。