Python数据类型之“文本序列(Text Sequence)”

时间:2021-07-08 12:52:13

Python中的文本序列类型


Python中的文本数据由str对象或字符串进行处理。

1.字符串

字符串是Unicode码值的不可变序列。字符串字面量有多种形式:

  • 单引号:'允许嵌入"双"引号'
  • 双引号:"允许嵌入'单'引号"
  • 三引号:'''三个单引号''', """三个双引号"""

说明:

a) 三引号的字符串可以跨越多行,所关联的空格将包含在字符串文字中;

b) 字符串也可以使用str构建函数从其他对象创建;

c) 因为没有单独的“字符”类型,因此索引字符串将产生长度为1的字符串。也就是说,对于非空字符串s,s[0] == s[0:1];

d) 没有可变的字符串类型,但是str.join()或io.StringIO可以用于从多个片断有效地构造字符串;

e) 字符串中可以是用反斜线"\"对特殊字符进行转义,也可以在字符串字面上使用"r"前缀来取消转义;

f) Python 3.3中的修改:为了向后兼容Python 2系列,在字符串字面上再次允许使用"u"前缀,但是它对字符串文字的含义没有影响,也不能与"r"前缀组合使用;

g) 作为单个表达式的一部分并且在它们之间只有空格的字符串文字将被隐式转换为单个字符串文字。也就是说("spam""eggs") == "spam eggs";

2.str类

str类构建方法

class str(object='')
class str(object=b'', encoding='utf-8', errors='strict')

str类的构建方法返回对象的字符串版本。如果未提供对象参数,则返回空字符串。否则,str()的行为取决于是否给出了encoding和errors参数,如下所示:

  • 如果既没有给出encoding也没有给出errors参数,str(object)将会返回object.str()的值,这是object的“非正式”或可打印的字符串表示。对于字符串对象,这是字符串本身。如果该object没有__str__()方法,那么str()将会返回repr(object)的结果值。
  • 如果给出了encoding或errors两个参数中的至少一个,则object应该是类似于字节的对象(例如bytes或bytearray)。在这种情况下,如果object是bytes(或 bytearray)对象,则str(bytes,encoding,errors)等价于bytes.decode(encoding, errors)。
  • 将字节对象传递给str()而不使用encoding或errors参数属于返回非正式字符串表示形式的第一种情况。

str构建示例

>>> 'Hello, World!'  # 单引号
'Hello, World!'
>>> "Hello, World!" # 双引号
'Hello, World!'
>>> """ # 三引号,多行
... Hello,
... World!
... """
'\nHello,\nWorld!\n'
>>> "Hello, \"World!\"" # 使用转义
'Hello, "World!"'
>>> str() # 不给出object参数,返回空字符串
''
>>> str("Hello, World!") # 给出object参数,但不给出encoding和errors
'Hello, World!'
>>> str(b"Hello, World!")
"b'Hello, World!'"
>>> str(b"Hello, World!", encoding='utf-8') # 给出object参数,也给出encoding参数
'Hello, World!'

3.文本序列支持的操作

由于文本序列是一个特殊的(专门处理文本)不可变序列,因此它不支持可变序列特有的操作,但是它支持所有的序列通用操作。下面介绍下str支持的除序列通用操作外的其他方法:


# 返回一个将字符串居中的指定长度的字符串,填充部分使用fillchar指定的字符来完成(默认为ASCII空格)。如果width小于或等于len(s),则返回原始字符串
str.center(width[,fillchar])
# 与center()方法类似,只是字符串位于左边, 填充字符位于右边
str.ljust(width[,fillchar])
# 与center()方法类似,只是字符串位于右边,填充字符位于左边
str.rjust(width[,fillchar])
# 在数字字符串左侧以ASCII的'0'数字进行填充,形成一个长度为width的字符串副本,并返回。如果数字字符串中包含前缀符号(如 '+'/'-')则'0'会被插入到前缀字符与数字字符之间。如果width<=len(s),则返回原始字符串。
str.zfill(width) # 返回字符串删除指定的前导字符和尾随字符之后的副本。可选参数chars是一个字符串,用来指定要删除的字符集合,如果省略或为None则chars参数默认为删除空格。注意:chars参数不是前缀或后缀字,相反,它包含的字符的所有组合都会被删除。
str.strip([chars])
# 与strip()方法类似,只是仅删除字符串的前导字符
str.lstrip([chars])
# 与strop()方法类似,只是仅删除字符串的尾随字符
str.rstrip([chars]) # 返回子串sub在切片s[start:end]中第一次出现的索引位置,如果子串sub不存在则返回-1。需要注意的是,只有当需要知道sub的位置时,才应该使用find()方法,如果要检查sub是否是字符串的子串,请使用in运算符。
str.find(sub[,start[,end]])
# 返回子串sub在切片s[start:end]中最后一次出现的索引位置,如果子串sub存在则返回-1。
str.rfind(sub[, start[, end]]) # 该方法类似于find(),但是如果子串未找到会抛出ValueError异常。
str.index(sub[, start[, end]])
# 该方法类似于rfind(),但是如果子串为找到会抛出ValueError异常。
str.rindex(sub[, start[, end]]) # 返回在范围[start, end]内指定的字符串sub不重叠出现的次数。
str.count(sub[, start[, end]])
# 将字符串的编码版本作为字节对象返回,默认编码为“utf-8”。errors的默认值为"strict",意味着编码错误会引发UnicodeError,其他可能的值为"ignore", "replace"等。
str.encode(encoding="utf-8", errors="strict") # 以当前字符串为连接符把iterable中的所有字符串连接成一个字符串并返回,如果iterable中存在非字符串值(包括bytes对象),将会抛出TypeError异常。
str.join(iterable)
# 用sep参数的值作为分隔符对字符串进行分割,返回一个字符串列表。如果maxsplit参数被给出,那么最多进行maxsplit次分割操作(因此,得到的字符串里列表将最多有maxsplit+1个元素);如果maxsplit没有被指定或指定为-1,则不限制分割次数。
str.split(sep=None, maxsplit=-1)
# 用split()函数类似,只是它从右向左进行分割。
str.rsplit(seq=None, maxsplit=-1)
# 在字符串中的行边界位置进行切割,返回一个行的列表。可选参数keepends为一个布尔值,表示换行符是否包含结果列表中,默认为false。这里的行边界包括'\n', '\r', '\r\n'等。|
str.splitlines([keepends]) # 该静态方法将返回一个可用于str.translate(table)方法的转换表(字典)。如果只有一个参数,它必须是一个将Unicode ordinals(整数)或字符(长度为1的字符串) 映射为 Unicode ordinal(整数),字符串(任意长度)或None的字典映射。字符键值将被转换为整数。如果有两个参数,它们必须是相同长度的字符串,并且在结果字典中,x中的每个字符将被映射到y中相同位置的字符。如果有第三个参数,它必须是一个字符串,其字符将在结果字典中被映射为None。
static str.maketrans(x[, y[, z]])
# 返回一个字符串副本,通过给定的转换表table将字符串副本中的每个字符转换为对应的值(字符/字符串/None)。table参数必须是通过__getitem__()实现索引的对象,通常是映射或序列。当使用Unicode序号(整数)索引时,table对象可以执行以下任何操作:返回Unicode序号或字符串,可以将字符映射到一个或多个其它字符;返回None,可以从返回字符串中删除字符;将字符映射到自身,将引发LookupError异常。
str.translate(table) # 返回一个将字符串中的所有小写字母转为大写的字符串拷贝。
str.upper()
# 返回一个将字符串中的所有大写字母转为小写的字符串拷贝。
str.lower()
# 返回一个将字符串中的所有大写字母转为小写,将所有的小写字母转为大写的字符串拷贝。
str.swapcase()
# 返回一个将第一个字母转为大写的字符串拷贝。
str.capitalize()
# 返回一个将所有单词首字母转为大写的字符串拷贝。
str.title() # 如果字符串以指定的前缀prefix开始,则返回True,否则返回False。后缀也可以是一个后缀元祖。可选参数start和end可以指定查找前缀的开始和结束位置。
str.startswith(prefix[, start[, end]])
# 如果字符串以指定的后缀suffix结尾,则返回True,否则返回False。后缀也可以是一个后缀元祖。可选参数start和end可以指定查找后缀的开始和结束位置。
str.endswith(suffix[, start[, end]]) # 如果字符串中至少有一个字符,且所有字符都是十进制字符则返回True,否则返回False。此类别包括十进制数字和所有可用于形成十进制数字的字符,如 U+0660, ARABIC-INDIC DIGIT ZERO。
str.isdecimal()
# 如果字符串中至少有一个字符,且所有字符都是数字则返回True, 否则返回False。数字包括十进制字符和需要特殊处理的数字,形式上,数字是具有属性值Numeric_Type = Digit 或 Numeric_Type = Decimal的字符。
str.isdigit()
# 如果字符串中至少有一个字符,且所有字符都是数字字符则返回Ture, 否则返回False。这里的数字字符包括digit字符和所有具有Unicode数字值属性的所有字符。形式上,这里的数字字符是指具有属性值Numeric_Type = Digit, Numeric_Type = Decimal 或 Numeric_Type = Numeric的字符。
str.isnumeric()
# 如果字符串中至少有一个字符,且所有字符都是字母则返回True,否则返回False。
str.isalpha()
# 如果字符串中至少有一个字符,且所有字符都是numeric或alpha则返回Ture, 否则返回False。即只要上面4个方法中的任意一个方法调用返回Ture则该方法调用就返回Ture。
str.isalnum()
# 如果字符串中至少有一个字符,且所有字符都是空白字符则返回True, 否则返回False。
str.isspace()

文本序列操作示例

>>> 'welcome'.center(15, '-')
'----welcome----'
>>> 'welcome'.ljust(15, '-')
'welcome--------'
>>> 'welcome'.rjust(15, '-')
'--------welcome'
>>> '11'.zfill(15)
'000000000000011'
>>>
>>> ' spacious '.strip()
'spacious'
>>> 'www.example.com'.strip('cmowz')
'.example.'
>>> ' spacious '.lstrip()
'spacious '
>>> 'www.example.com'.lstrip('cmowz')
'.example.com'
>>> ' spacious '.rstrip()
' spacious'
>>> 'mississippi'.rstrip('ipz')
'mississ'
>>>
>>> 'Hello, Lilly'.find('ll')
2
>>> 'Hello, Lilly'.find('ll', 4)
9
>>> 'Hello, Lilly'.rfind('ll')
9
>>> 'Hello, Lilly'.rfind('ll', 0, 7)
2
>>> 'Hello, Lilly'.index('ll')
2
>>> 'Hello, Lilly'.index('ll', 4)
9
>>> 'Hello, Lilly'.rindex('ll')
9
>>> 'Hello, Lilly'.rindex('ll', 0, 7)
2
>>> 'Hello, Lilly'.find('lll')
-1
>>> 'Hello, Lilly'.index('lll')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: substring not found
>>>
>>> ':'.join(['Tom', 'Jerry', 'Peter'])
'Tom:Jerry:Peter'
>>> 'Tom:Jerry:Peter'.split()
['Tom:Jerry:Peter']
>>> 'Tom:Jerry:Peter'.split(sep=':')
['Tom', 'Jerry', 'Peter']
>>> 'Tom:Jerry:Peter'.split(sep=':', maxsplit=1)
['Tom', 'Jerry:Peter']
>>> 'Tom:Jerry:Peter'.rsplit(sep=':')
['Tom', 'Jerry', 'Peter']
>>> 'Tom:Jerry:Peter'.rsplit(sep=':', maxsplit=1)
['Tom:Jerry', 'Peter']
>>> 'Tom:Jerry::Peter:'.split(sep=':') # 空值不会被合并,可能需要单独进行空值判断
['Tom', 'Jerry', '', 'Peter', '']
>>> 'ab c\n\nde fg\rkl\r\n'.splitlines() # 末尾的行尾标记不会产生一个额外的行
['ab c', '', 'de fg', 'kl']
>>> 'ab c\n\nde fg\rkl\r\n'.splitlines(keepends=True)
['ab c\n', '\n', 'de fg\r', 'kl\r\n']
>>>
>>> 'abcdedfg'.translate({'a':'A', 'd': 'D'}) # 转换表中的key应该是字符对应的Unicode数字值,而不应该是字符本身
'abcdedfg'
>>> 'abcdedfg'.translate({97: 'A', 100: 'D'})
'AbcDeDfg'
>>> str.maketrans({'a': 'A', 'd': 'D'})
{97: 'A', 100: 'D'}
>>> table = str.maketrans({'a': 'A', 'd': 'D'}) # 这样就不要是查字符对应的Unicode数字值是多少了
>>> 'abcdedfg'.translate(table)
'AbcDeDfg'
>>>
>>> 'hello, world!'.upper()
'HELLO, WORLD!'
>>> 'hello, world!'.upper().lower()
'hello, world!'
>>> 'Hello, World!'.swapcase()
'hELLO, wORLD!'
>>> 'hello, world!'.capitalize()
'Hello, world!'
>>> 'hello, world!'.title()
'Hello, World!'

4.字符串的格式化

在几乎所有的编程语言中,字符串的格式化都是非常重要的基本知识。Python中实现字符串格式化有以下几种方式:

  • 字符串拼接(不推荐使用)
  • 符串本身所支持的方法调用:str.format(*args, **kwargs)
  • 字符串的内置操作符:%

通过字符串拼接实现式化

>>> a = 2
>>> b = 3
>>> str(a) + ' + ' + str(b) + ' = ' + str(a+b)
'2 + 3 = 5'

此处通过字符串的拼接来输出一定格式的字符串,这会在内存中产生多个字符串对象,且操作复杂,容易出错。

使用str.fromat()进行字符串格式化

该方法用于执行字符串格式化操作。调用此方法的字符串可以包含由大括号字面文本或由大括号{}分割的替换字段。每个替换字段保存位置参数的数字索引或关键字参数的名称。该方法将返回一个字符串副本,其中每个替换字段都替换为相应参数的字符串值。

>>> a = 2
>>> b = 3
>>> '{0} + {1} = {2}'.format(a, b, a+b) # 使用位置参数
'2 + 3 = 5'
>>> '{a} + {b} = {c}'.format(a=a, b=b, c=a+b) # 使用关键字参数
'2 + 3 = 5'
>>> '{a} + {b} = {c}'.format({'a': a, 'b': b, 'c': a+b}) # 不能使用字典
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'a'

str.format()可以实现简单的字符串格式化,但是这种格式化方式存在一些怪癖,比如它不支持接收元组(tuple)、字典(dict)等数据类型作为参数,这是非常不方便的。

使用字符串内置操作符(%)进行字符串格式化

%操作符是字符串对象唯一的内置操作,也称为字符串格式化或插值运算符。该接口提供了一种更强大、灵活和可扩展的方法来格式化文本。格式字符串中的% 转换规范将会被替换为0个或多个元素的值,效果类似于在C语言中使用sprintf()。

如果格式字符串需要单个参数,那么替换值可以是单个非元组对象;否则,替换值必须是具有由格式化字符串指定的条目数量的元组,或者是单个映射对象(例如,字典)。

>>> 'The sum of 2 + 3 is: %d' % 5  # 格式化字符串只需要1个参数,替换值可以是的那个非元组字符
'The sum of 2 + 3 is: 5'
>>>
>>> a = 2
>>> b = 3
>>> '%d + %d = %d' % (a, b, a+b) # 格式化字符串需要n(n > 1)个参数,替换值需要是具有n个元素的元组
'2 + 3 = 5'
>>> '%(a)d + %(b)d = %(c)d' % {'a': a, 'b': b, 'c': a+b} # 格式化字符串需要n(n > 1)个参数,替换也可以是具有n个元素的映射对象
'2 + 3 = 5'
>>>

上面示例中,格式字符串中的 %d, %(a)d称为“转换说明标识符”。这个标识符可以由2个或多个部分组成,且各部分必须按照指定的顺序排列:

  • '%'字符:表示“转换说明标识符”的开始;
  • 映射键名称(Mapping key): 可选部分,由小括号包含的字符串序列组成,如:(name);
  • 转换标识(Conversion flags):可选部分,这个会影响一些转换类型的结果;如:'0'表示用数字字符0进行填充,'-'表示左对齐(用空白字符进行右填充)
  • 最小字段宽度(Minimum field width): 可选部分,指定转换结果的最小宽度
  • 精度(Precision): 可选部分,通过".精度值"的方式来指定小数点后保留几位小数
  • 长度修饰符(Length modifier): 可选部分
  • 转换类型(Conversion type): 用于指定数据类型;常用的转换类型有 'd'或'i'表示有符号十进制整数,'f'或'F'表示浮点数,'s'表示字符串, '%'表示其本身

由上可见,在“转换说明表示符”的7个组成部分中,只有第1部分"%",和最后一部分"转换类型"是必须的指定的,其他部分都是可选的辅助项。另外,长度修饰符(h,l或L)可以存在,但是将被忽略,因为对于Python不是必要的。也就是说,ld与%d是相同的。

>>> student01 = {'name': 'Peter', 'sno': 15, 'age': 22, 'score': 93.92532}
>>> msg = '''
... ##### Information of student: %(name)s #####
... 姓名:%(name)s
... 学号:%(sno)010d
... 年龄:%(age)d
... 得分:%(score).2f
... ----- end -----
... ''' % student01
>>> print(msg) ##### Information of student: Peter #####
姓名:Peter
学号:0000000015
年龄:22
得分:93.93
----- end ----- >>>