作者: Jim Wang 公众号: 巴博萨船长

Python 定义了一些标准数据类型,用于存储各种类型的数据。Python有五个标准的数据类型,分别是:

  • Numbers(数字)
  • String(字符串)
  • List(列表)
  • Tuple(元组)
  • Dictionary(字典)

字符串作为Python编程的常用数据类型,在代码中出现的频率相当高。今天借着这篇文章来给大家介绍一下关于Python编程中,String字符串这种数据类型的基本知识和实际运用中会遇到的问题及解决方法,同时也给大家介绍一些常用的使用技巧。

img

String字符串的特征

前几篇文章中都有介绍,Python的变量声明简单明确。字符串类型的变量声明也十分简单,任何用引号包裹的内容都可以理解为字符串,无论是单引号(single quotes),或者是双引号 (double quotes), 还是三引号(triple quotes)。如下:

1
2
3
4
>>> st = 'Hallo World'  # 单引号
>>> st = "Hallo World" # 双引号
>>> st = """Hallo World""" # 三引号
>>> st = u"Hallo World" # unicode 宽字符串

有时作为输出需要,还是要将引号本身作为字符串的一部分输出来了。这时候需要引号套用,在Python中,每种引号都可以包含其他的引号,如果要包含引号自身则需要”转义”。如下:

1
2
3
4
5
6
7
8
9
10
11
12
>>> print 'Hallo " World'  # 单引号 包含双引号
Hallo " World
>>> print 'Hallo """ World' # 单引号 包含双引号
Hallo """ World
>>> print "Hallo ' World" # 双引号 包含单引号
Hallo ' World
>>> print 'Hallo \' World' # 单引号 包含单引号(转义)
Hallo ' World
>>> print r'Hallo \' World' # 停止 转义
Hallo \' World
“转义” 的意思是告诉解释器或编译器,转义符后面的一个或者几个
字符串要使用一种替代的解释或者编译方式。

“转义”在很多程序语言中都有用到。那么问题来了,Python中的转移符号位反斜杠”"。如果根据输出需要:在单引号包含单引号(转义)的情况下,在包含的单引号前显示一个反斜杠符号”",该如何实现。方法如下。

1
2
3
4
>>> print 'Hallo \' World'  # 为了显示包含的单引号
Hallo ' World
>>> print 'Hallo \\\' World' # 为了现实单引号和反斜杠
Hallo \' World

上面的例子中第二行代码中的<\‘>。这部分内容应该这样理解:第三个反斜杠是用于转义单引号字符。第一个反斜杠是用于转义第二个反斜杠。转义符的复用和套用会在实际应用中经常出现,如在处理字符串的大杀器正则表达式中,许多语法就用到转移符。如果能够正确使用转义符,也有助于快速理解代码和准确调试代码。

上一篇文章介绍过,Python中的字符也属于序列类型(Sequence),且为非可变序列类型,作为序列,它可以是迭代(iterable),可以历遍(traverse)。这样的就赋予了字符串一些特殊的性能。比如类似与元组,可以使用for或者enumerate来历遍整个字符串中的字符。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> for a in "Hallo World":
... print a
...
H
a
l
l
o
...
>>> for i, a in enumerate("Hallo World"):
... print `i` + " " + a
0 H
1 a
2 l
3 l
4 o
...

在判断元素是否存在与序列中是, 用到的逻辑判断关键字 innot in 也适用于字符串。 类似元组和列表的索引和切片方式也同样适用于字符串,在这里就不赘述了。需要指出,在逻辑判断时,准确地说,在比较两个字符串是否相等时,虽然可以使用关键字 “is“ 或逻辑判断符 “==“ 或者cmp( ) 函数等。但是三者还是有所不同的。在Python中 “is” 是用于判断两个变量是否引用的是同一对象;逻辑判断符 “==” 用于判断两个变量的值是否相同;cmp( ) 函数的用法和逻辑判断符 “==” 相似。在Python3 中,该函数被移除了。考虑到代码的兼容性和稳定性,建议在对比字符串是否相同时采用逻辑判断符 “==”。

值得注意的是,上述的例子中我用到了反引号,在Python中反引号,内置函数str( )repr( ) 都是用来将非字符串类型转换为字符串类型的。 三者相似但不相同:

  1. 反引号, 该语法只适用于Python2.7 中,Python3.0已经不再

    支持该语法。

  2. str(), 使用该方法得到的字符串具有很好的可读性。非常适

    用于print的输出。

  3. repr(), 用于返回一个类实例的标准字符串表示,至于如何

    表现,可以在类中的repr(self),方法中定义。该方法的

    特点为,该方法一般情况下:

    适用等式: obj = eval(repr(obj)) 。意味着可以使用该等

    式从字符串中重新获得该对象。

需要强调:字符串作为不可变序列。意味着,字符在初始化之后,就不能再对字符串的实例进行改变。字符串的自加和拼接,虽然都可以使用相同的变量名来接收新的值,但本质上是申明了一个新的字符串变量,只是名字相同而已,比如:

1
2
3
4
5
6
7
8
9
10
11
12
>>> my_string = "AAA "
>>> id(my_string)
42835040L
>>> my_string += "AAA "
>>> id(my_string)
42794176L
>>> my_string = "AAA "
>>> id(my_string)
42834960L
>>> my_string = "AAA " + " BBB"
>>> id(my_string)
42794416L

由上述例子可知,虽然使用了相同的变量名,用来接收新的值,但随着字符串变量值的变化,对象的id也发生了变化,也就意味着虽然变量名称不变,但是其本质上已经是一个新的变量

String字符串的类方法

字符串作为一个类,即对象。也就意味了它会有类方法和类属性,随着Python的日渐完善。字符串的类方法也日渐健全与强大,字符串的类方法有很多,在此只列举出一些经常遇见的类方法,请看下方表格:

string.isalnum() 判断 string 中是否所有字符都是字母或数字。是则返回 True,否则返回 False
string.isalpha() 判断 string 中是否含有字符并且所有字符都是字母,是则返回 True,否则返回 False
string.isdecimal() 判断 string 中是否只包含十进制数字,是返回 True 否则返回 False.
string.isdigit() 判断 string 中是否只包含数字,是则返回 True,否则返回 False.
string.islower() 判断 string 中是否包含一个或者多个区分大小写的字符,字符都是小写。则返回 True,否则返回 False
string.istitle() 判断 string 中是否第一个字符为大写。是则返回 True,否则返回 False
string.isupper() 判断string 中是否所以字符都是大写。 则返回 True,否则返回 False
string.lower() 讲转换 string 中所有字符转变为小写.
max(str) 返回字符串 str 中最大的字母,参考 ascii 表。
min(str) 返回字符串 str 中最小的字母,参考 ascii 表。
string.title() 将所有单词都是的第一个字母大写,其余字母均为小写
string.upper() 转换 string 中的所有字母改为大写

熟练掌握上述类方法在Python编程中很有益处,比如:在遇见到需要将数字型的字符串转化为数值型变量时。如果可以先使用string.isdigit()这个类方法对变量进行检查,就能够避免因出现转换异常(Exception)造成整个程序的意外退出。

与类方法相匹配,Python还提供了一些模块用于辅助处理字符串。例如,常见的文件操作中,需要对文件路径进行处理。该变量在Python也是字符串类型。如需要对路径进行拼接和拆分,获取文件名或文件后缀类型。Python中的os.path模块就非常适合做这样的工作,如下:

1
2
3
4
5
6
7
8
>>> import os
>>> my_path = "C:\\temp\main.py"
>>> os.path.split(my_path)
('C:\\temp', 'main.py')
>>> os.path.splitext(my_path)
('C:\\temp\\main', '.py')
>>> os.path.join("C:\\tmp", "main.py")
'C:\\tmp\\main.py'

在处理路径是,申明路径字符串变量时,尽量使用双反斜杠,这样可以避免一些错误异常。如果我们使用os.path模块下的函数来处理路径,就能够尽可能地避免很多对反斜杠的操作。代码也能够简洁高效。

String字符串的转码问题

常见的字符处理事务中还会遇见字符串转码问题。由于计算机只能处理数字,处理文本类的时候也需要先将文本类转换为数字。在编程中,字符串独立作为一种数据类型,但是其本身在内存中也是一组数字。如何将文本类转换为数字,就是我们要讨论的编码问题。

Unicode也称为宽字节字符。Unicode的目的是将所有语言都统一到一套编码里,从而避免乱码问题。举个例子:

1
2
字母 A 用ASCII编码是十进制的65,二进制的01000001。
字母 A 用Unicode编码, 编码是00000000 01000001。

可以看出,如果将字母 A 转变成 Unicode,则编码长度变长,但其值不发生变化,因为低字节已经足以满足要求,但最为宽体字符我们需要在高字节补零。如果一个Unicode字符,其高字节不全为零,强制性将其转换为ASCII编码字符。就会发生错误: 超出编码范围。

文中插图中强调 “unicode” != “utf-8” 。意思是说utf-8是编码方式,除了常见的的uft-8还有utf-16,以及中文编码方式gbk等等。unicode 则是这些转码后的宽字符串的统称。在Python中,可以将unicode理解为一种新的字符串数据类型。该字符串与普通ascii字符串用法相似,但它能够接收和处理非ascii编码的文本类型。举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
#-*- coding: gbk -*-
string='中国'
print "string: ", type(string)
print string

ustring=u"中国"
print "ustring: ",
type(ustring)
print ustring

gbkstring=ustring.encode("gbk")
print "gbkstring: ", type(gbkstring)
print gbkstring

输入结果为:

1
2
3
4
5
6
string: <type 'str'>
我的
ustring: <type 'unicode'>
鎴戠殑
gbkstring: <type 'str'>
我的

上述例子中unicode接收了宽体字符,它也作为媒介用于实现字符串编码的转换。而只有准确的将unicode编码解码,才能得到正确的结果。

String字符串的查找与替换

处理String字符串的终极问题是:从字符串特定位置,得到符合特定条件的子字符串或者在符合特定条件的位置插入子字符串。解决类似问题的大杀器就是Python的正则表达式。文章篇幅问题,关于正则表达式的内容在以后的文章里面介绍。本文就简单介绍一下find( ) 和 replace( ) 两个函数。

find也好repleace 也罢,都是string类的类方法,可作为实例方法,也可以作为该类的静态方法。举个例子:

1
2
3
4
5
6
7
8
9
10
>>> import string
>>> my_str = 'abca'
>>> my_str.find('a') # 实例方法
0
>>> string.find(my_str, 'a') # 静态方法
0
>>> my_str.find('a', 1)
3
>>> string.find(my_str, 'a', 1)
3

要找到特定字符在字符串中的位置,最好是给定查找的初始位置。默认情况下初始位置为零,而且该方法找到即返回,不会迭代查找。如果没有找到则返回值为-1,这里的 “-1” 可以用于逻辑判断。

repleace方法和find方法近似。但是默认情况下会替换字符串中所有符合条件的字符。如果想删除字符串中的某些字符,则可以将用于替换的字符设置为空,如下:

1
2
3
4
>>> str ="ab1cd1ef"
>>> str.replace("1","")
'abcdef'
>>>

Python基本数据类型中的字符串和其使用技巧今天就介绍到这里。欢迎订阅我的个人微信公共号,如果您有问题或者不同见解,请在下方留言。


版权声明:
文章首发于 Jim Wang's blog , 转载文章请务必以超链接形式标明文章出处,作者信息及本版权声明。