字符串常量和操作
re模块(正则表达式)
-
-
- 除了核心系列的字符串工具以外,Python通过标准库re模块(正则表达式)还支持更高级的基于模式的字符串处理
-
Python3中,有3种字符串类型
-
-
- str用于Unicode文本(ASCII或其他)
- bytes用于二进制数据(包括编码的文本)
- bytearray是bytes的一种可变的变体
-
单双引号字符串是一样的
-
-
- Python自动在任意的表达式中合并相连的字符串常量,尽管可以简单地在它们之间增加+操作符来明确地表示这是一个合并操作
- 注意:在字符串之间增加逗号会创建一个元组,而不是一个字符串。并且Python倾向于打印所有这些形式的字符串为单引号,除非字符串内有了单引号了。你也可以通过反斜杠转义字符去嵌入引号
- Python自动在任意的表达式中合并相连的字符串常量,尽管可以简单地在它们之间增加+操作符来明确地表示这是一个合并操作
-
>>> 'knigth's', "knight"s"
("knigth's", 'knight"s')
用转义序列代表特殊字节
-
-
- 反斜杠用来引入特殊的字节编码, 是转义序列
- 转义序列让我们能够在字符串中嵌入不容易通过键盘输入的字节
- 字符串常量中的字符“”,以及在它后面的一个或多个字符,在最终的字符串对象中会被一个单个字符所替代,这个字符通过转义序列定义了一个二进制值
-
>>> s = 'anbtc'
>>> s
'anbtc'
>>> print(s)
a
b c
-
- 两个字符“n”表示一个单个字符——换行字符的字节。类似的,序列“t”替换为制表符
- 这个字符串打印时的格式取决于打印的方法
- 交换模式下是以转义字符的形式回显的
- print会将其解释出来
- 使用len函数,它会返回一个字符串到底有多少字节
- 注意
- 原始的反斜杠字符并不真正和字符串一起存储在内存中
- 它们告诉Python字符串中保存的特殊字节值
字符串反斜杠字符
-
-
- Uhhhhhhhh转义序列带有八个十六进制数字(h)
- u和U只能使用于Unicode常量之中
- 一些转义序列允许一个字符串的字节中嵌入绝对的二进制值
-
raw字符串抑制转义
-
-
- 字母r(大写或小写)出现在字符串的第一引号的前面,它将会关闭转义机制
-
三重引号编写多行字符串块
-
-
- 三重引号字符串在程序需要输入多行文本的任何时候都是很有用的
- 例如,嵌入多行错误信息或在源文件编写HTML或XML代码。我们能够直接在脚本中嵌入这样的文本块而不需要求助于外部的文本文件,或者借助直接合并和换行字符
- 三重引号字符串常用于文档字符串,当它出现在文件的特定地点时,被当作注释一样的字符串常量。这并非只能使用三重引号的文本块,但是它们往往是可以用作多行注释的
- 三重引号字符串在程序需要输入多行文本的任何时候都是很有用的
-
索引和切片
-
-
- Python偏移量是从0开始的,并比字符串的长度小1
- Python支持类似在字符串中使用负偏移这样的方法从序列中获取元素
- 从技术上讲,一个负偏移与这个字符串的长度相加后得到这个字符串的正的偏移量
- 能够将负偏移看做是从结束处反向计数
-
>>> s = 'spam'
>>> s[0],s[-2],s[:],s[1:],s[:-1]
('s', 'a', 'spam', 'pam', 'spa')
-
- 偏移和切片
- 位置偏移从左至右(偏移0位第一个元素),而负偏移是由末端右侧开始计算(偏移-1位最后一个元素)
- 这两种偏移均可以在索引和分片中作为所给出的位置
- 当你对字符串应用分片时——它让我们能够从一整个字符串中分离提取出一部分内容(子字符串)
- 分片可以用作提取部分数据,分离出前、后缀等场合
- 分片是如何运作的
- 当使用一对以冒号分隔的偏移来索引字符串这样的序列对象时,Python将返回一个新的对象,其中包含了以这对偏移所标识的连续的内容
- 左边的偏移作为下边界(含),而右边的偏移作为上边界(不含)
- Python将获取从下边界直到上边界(不含)的所有元素,并返回一个包含了所获取的元素的新的对象
- 如果被省略,上、下边界的默认值对应分别为0和分片的对象的长度
- s[:-1]获取了除了最后一个元素之外的所有元素
- s[:]获取了从偏移0到末尾之间的元素,实现一个完全的顶层的序列对象的拷贝
- 一个有相同值,但是是不同内存片区的对象
- 偏移和切片
扩展分片:第三个限制值
-
-
- 分片表达式增加了一个可选的第三个索引,用作步进(有时称为是stride)
- 步进添加到每个提取的元素的索引中
- 完整形式的分片:X [ I : J : K ]
- 表示索引X对象中的元素,从偏移为I直到偏移为J-1,每隔K元素索引一次
- 第三个限制——K,默认为1
- 第一和第二限制值默认为0以及序列的长度
-
>>> s = 'abcdefghijklmnop'
>>> s[1:10:3]
'beh'
>>> s[::2]
'acegikmo'
-
- 也可以使用负数作为步进
>>> s = 'hello'
>>> s[::-1]
'olleh'
-
- 步进-1表示分片将会从右至左而不是通常的从左至右
- 实际效果就是将序列进行翻转
- 通过一个负数步进,两个边界的意义实际上进行了反转
>>> s[5:1:-1]#等效为s[2:6],内容为oll
'oll'
>>> s[1:5:-1] ''#等效为s[6:2],内容为空。
-
- s[i:j:-1] = s[j+1:i+1]
字符串转换工具
-
-
- int函数将字符串转换为数字
- str函数将数字转换为字符串表达形式(看起来和打印出来的效果是一样的)
- repr函数将一个对象转换为字符串形式
-
>>> str('hello')
'hello'
>>> repr('hello')
"'hello'"
-
- 对于字符串来说,如果是使用print语句进行显示的话,其结果需用引号括起来
- int和str是通用的指定转换工具
字符串代码转换
-
-
- 内置ord函数可以将单个字符转换为其对应的ASCII码
- 内置chr函数将会执行相反的操作
-
>>> ord('s')
115
>>> chr(115)
's'
-
- 可以利用循环完成对字符串内所有字符的函数运算,也可以用来执行一种基于字符串的数学运算,例如,为了生成下一个字符,我们可以预先将当前字符转换为整型并进行如下的数学运算:
>>> s = '5'
>>> s = chr(ord(s) + 1)
>>> s
'6'
>>> s = chr(ord(s) + 1)
>>> s
'7'
-
- 对于单个字符的字符串,可通过调用内置函数int,转换为整数
>>> int("5")
5
>>> ord('5') - ord('0')
5
-
- 转换可以与循环语句遗弃配合使用,可以将一个表示二进制数的字符串转换为等值的整数,每次都讲当前的值乘以2,并加上下一个数字的整数值
>>> a = '1101'
>>> i = 0
>>> while a != '':
... i = i*2 + (ord(a[0]) - ord('0'))
... a = a[1:]
...
>>> i
13
-
- 左移运算(i<<1)与在这里乘2的运算是一样的
- 内置函数int和bin可以用来处理二进制转换任务
>>> int('1101', 2)
13
>>> bin(13)
'0b1101'
修改字符串
-
-
- 不可变序列:不能在原地修改一个字符串,如给一个索引进行赋值
- 改变一个字符串,需要利用合并、分片这样的工具来建立并赋值给一个新的字符串
-
>>> s = 'spam'
>>> s = s[:2] + 'ger'
>>> s
'spger'
-
- 同样可以通过像replace方法来实现
>>> s = 'spam'
>>> s = s.replace("s", "yyy")
>>> s
'yyypam'
-
- 可以通过字符串格式化表达式来创建新的文本值,下面的两种方式都把对象替换为字符串,在某种意义上,是把对象转换为字符串并且根据指定的格式来改变最初的字符串
>>> 'That is %d %s bird!' % (1, 'dead')
'That is 1 dead bird!'
>>> 'That is {0} {1} bird!'.format(1, 'dead')
'That is 1 dead bird!'
-
- 尽管用替换这个词来比喻,但格式化的结果是一个新的字符串对象,而不是修改后的对象
字符串方法
-
-
- 在Python中,表达式和内置函数可能在不同范围的类型有效,但方法通常特定于对象类型
- 字符串方法仅适用于字符串对象
- Python3中某些类型的方法集有所交叉(如很多类型都有一个count方法),但它们仍然比其他的工具更加特定于类型
- 更详细一点:函数也就是代码包,方法调用同时进行了两次操作(一次获取属性和一次函数调用):
- 属性读取
- 具有object.attribute格式的表达式可以理解为“读取object对象的属性attribute的值”
- 函数调用表达式
- 具有函数(参数)格式的表达式意味着“调用函数代码,传递零或者更多用逗号隔开的参数对象,最后返回函数的返回值”
- 将两者合并可以让我们调用一个对象方法
- 方法调用表达式对象
- 方法(参数)从左到右运行
- 也就是说,Python首先读取对象方法,然后调用它,传递参数
- 如果一个方法计算出一个结果,它将会作为整个方法调用表达式的结果被返回
- 在Python中,表达式和内置函数可能在不同范围的类型有效,但方法通常特定于对象类型
-
字符串方法实例:修改字符串
-
-
- find方法返回在子字符串出现处的偏移(默认从前向后开始搜索)或者未找到时返回-1
- replace每次返回一个新的字符串对象,由于字符串是不可变的,因此每一种方法并不是真正在原处修改了字符串,尽管replace就是替换的意思
- 合并操作和replace方法每次运行会产生新的字符串对象,实际上利用它们去修改字符串是一个潜在的缺陷
- 如果你不得不对一个超长字符串进行许多的修改,为了优化脚本的性能,可能需要将字符串转换为一个支持原处修改的对象
- 内置的list函数(或一个对象构造函数调用)以任一序列中的元素创立一个新的列表,它可以将字符串的字符“打散”为一个列表
- 一旦字符串以这样的形式出现,你无需在每次修改后进行复制就可以对其进行多次修改
- 修改之后,如果你需要将其变会一个字符串,可以用字符串方法join将列表合成一个字符串
-
字符串方法实例:文本解析
-
-
- 分析结构并提取子串:为了提取固定偏移的子串,我们可以利用分片技术
- 数据出现在固定偏移处,可以通过分片从原始字符串分出来,这一技术称为解析
- 分析结构并提取子串:为了提取固定偏移的子串,我们可以利用分片技术
-
>>> line = 'aaa bbb ccc'
>>> col1 = line[0:3]
>>> col3 = line[8:]
>>> col1,col3
('aaa', 'ccc')
-
- 如果是有些分隔符分开了数据组件,可以使用split提取出这些组件
>>> cols = line.split()
>>> cols
['aaa', 'bbb', 'ccc']
-
- 字符串的split方法将一个字符串分隔为一个子字符串的列表,以分隔符为标准
- 默认的分隔符为空格——包括空格、制表符或者换行符
>>> line = """aaa
... bbb ccctddd"""
>>> line.split()
['aaa', 'bbb', 'ccc', 'ddd']
实际应用中的其他常见字符串方法
-
-
- 清理每行末尾的空白:rstrip()
- 执行大小写转换:upper()
- 测试内容都为英文字母:isalpha()
- 检测末尾或起始的子字符串:endswith(),startswith()
- 检测一个子字符串是否存在:成员操作符in
- 寻找子字符串的位置:find()
- Str[-len(str):] == str
-
字符串格式化表达式
-
-
- 字符串格式化允许在一个单个的步骤中对一个字符串执行多个特定类型的替换
- 它不是严格必须的,但它很方便使用,特别是当格式化文本以显示给程序的用户的时候
- 两种形式实现
- 字符串格式化表达式
- 字符串格式化方法调用
- Python在对字符串操作的时候定义了%二进制操作符。
- 当应用在字符串上的时候,%提供了简单的方法对字符串的值进行格式化,这一操作取决于格式化定义的字符串
- 简而言之,%操作符为编写多字符串替换提供了一种简洁的方法,而不是构建并组合单个的部分
- 格式化字符串
- 1.在%操作的左侧放置一个需要进行格式化的字符串,这个字符串带有一个或多个嵌入的转换目标,都以%开头(例如,%d)
- 2.在%操作符右侧放置一个(或多个,嵌入到元组中)对象,这些对象将会插入到左侧想让Python进行格式化字符串的一个(或多个)转换目标的位置上去
- 从技术上来讲,字符串的格式化表达式往往是可选的——通常你可以使用多次的多字符串的合并和转换达到类似的目的,然而格式化允许我们将多个步骤合并为一个简单的操作,这一功能相当强大
- %s,表示转换为字符串
-
更高级的字符串格式化表达式
-
-
- 字符串格式化代码
-
-
-
- 转换目标的通用结构:
-
%[(name)][flags][width][.precision]typecode
-
-
- 字符码出现在目标字符串的尾部,在%和字符码之间,你可以进行以下的任何操作:
- 放置一个字典的键——(name)
- 罗列出左对齐(-)、正负号(+)和补零(0)的标志位——flags
- 给出数字的整体长度和小数点后的位数等
- width和percision都可以编码为一个*,以制定他们应该从输入值的下一项中取值
- 字符码出现在目标字符串的尾部,在%和字符码之间,你可以进行以下的任何操作:
-
>>> x = 1234
>>> res = "integers: ...%d...%-6d...%06d" % (x, x, x)
>>> res
'integers: ...1234...1234 ...001234'
-
- %e、%f和%g格式对浮点数的表示方法有所不同(%E和%e相同,只不过指数是大写表示)
>>> x = 1.23456789
>>> '%e | %f | %g' % (x, x, x)
'1.234568e+00 | 1.234568 | 1.23457'
-
- 对浮点数来讲,通过制定左对齐、补零、正负号、数字位数和小数点后的位数,你可以得到各种格式化结果
- 对于较简单的任务来说,你可以通过利用简单的格式化表达式进行字符串转换或者str内置函数来完整
>>> '%-6.2f | %05.2f | %+06.1f' % (x, x, x)
#%-6.2f,左对齐,6位,小数点后2位精度,浮点十进制
#%05.2f,补零,5位,2位精度,浮点十进制
#%+06.1f,正负号,补零,6位,1位精度,浮点十进制
'1.23 | 01.23 | +001.2'
>>> "%s" % x, str(x)等效
('1.23456789', '1.23456789')
-
- 如果在运行的时候才知道大小,可以在格式化字符串中用一个*来指定通过计算得出width和precision,从而迫使它们的指从%运算符右边的输出中的下一项获取
>>> '%f, %.2f, %.*f' % (1/3.0, 1/3.0, 4, 1/3.0)#%f,转换为十进制浮点
#%.2f,小数点后两位十进制浮点
#%.*f,小树点后*位十进制浮点
#*位在前,数字在后
'0.333333, 0.33, 0.3333'
基于字典的字符串格式化
-
-
- 字符串的格式化同时也允许左边的转换目标来引用右边字典中的键来提取对应的值
-
>>> "%(n)d %(x)s" % {"n":1, "x":"spam"}
′1 spam′
-
- 格式化字符串里(n)和(x)引用了右边字典中的键,并提取它们相应的值。
可以建立一个数值字典,并利用一个基于键的引用的格式化表达式一次性替换它们
>>> reply = "Hello %(name)s! Your age squared is %(age)s."
>>> values = {′name′:′Bob′,′age′:40}
>>> print(reply % values)
Hello Bob! Your age squared is 40.
-
- 这样的小技巧也常与内置函数vars配合使用,这个函数返回的字典包含了所有的本函数调用时存在的变量
- vars() 函数返回对象object的属性和属性值的字典对象
- 当字典用在一个格式化操作的右边时,它会让格式化字符串通过变量名来访问变量(键)
- 这样的小技巧也常与内置函数vars配合使用,这个函数返回的字典包含了所有的本函数调用时存在的变量
>>> "%(age)d %(food)s" % vars()
′40 spam′
字符串格式化调用方法
-
-
- Python3中的新的字符串对象的format方法使用主体字符作为模板,并且接受任意多个表示将要根据模板替换的值的参数
- 在主体字符串中,花括号通过位置(如{1})或关键字(如{food})指出替换目标及将要插入的参数
- 函数和方法的参数可以使用位置或关键字名字来传递,并且Python收集任一多个位置和关键字参数的能力允许这种通用的方法调用模式
- Python3中的新的字符串对象的format方法使用主体字符作为模板,并且接受任意多个表示将要根据模板替换的值的参数
-
>>> ′{0}, {1} and {2}′.format(′spam′,′ham′,′egg′)
′spam, ham and egg′
>>> ′{motto}, {pork} and {food}′.format(motto=′spam′,pork=′ham′,food=′egg′)
′spam, ham and egg′
-
- 本质上字符串也可以是创建一个临时字符串的常量,并且任意的对象类型都可以替换
>>> ′{motto}, {0} and {food}′.format(42, motto=3.14, food=[1, 2])
′3.14, 42 and [1, 2]′
-
- 就像%表达式和其他字符串方法一样,format创建并返回一个新的字符串对象,它可以立即打印或保存起来方便以后使用
- 注意:字符串是不可变的,因此,format必须创建一个新的对象
- 就像%表达式和其他字符串方法一样,format创建并返回一个新的字符串对象,它可以立即打印或保存起来方便以后使用
添加键、属性和偏移量
-
-
- 格式化字符串可以指定对象属性和字典键,方括号指定字典键,而点表示位置或关键字所引用的一项的对象属性
- 如下例,索引字典上的键“spam”,然后从已经导入的sys模块对象获取“platform”属性,第二个例子做同样的事情,但是,通过关键字而不是位置指定对象:
- 格式化字符串可以指定对象属性和字典键,方括号指定字典键,而点表示位置或关键字所引用的一项的对象属性
-
>>> ′My {1[spam]} runs {0.platform}′.format(sys, {′spam′:′laptop′})
′My laptop runs darwin′
>>> ′My {config[spam]} runs {sys.platform}′.format(sys=sys,config={′spam′:′laptop′})
′My laptop runs darwin′
-
- 格式化字符串中的方括号可以指定列表(及其他的序列)偏移量以执行索引
- 但是,只有单个的正的偏移才能在格式化字符串的语法中有效
- 和%表达式一样,要指定负的偏移或分片,或者使用任意表达式,必须在格式化字符串自身之外运行表达式
- 格式化字符串中的方括号可以指定列表(及其他的序列)偏移量以执行索引
添加具体格式化
-
-
- 可以在格式化字符串中添加额外的语法来实现更具体的层级
- 对于格式化方法,我们在替换目标的标识之后使用一个冒号,后面跟着可以指定字段大小、对其方法和一个特定类型编码的格式化声明
- 在一个格式字符串中作为替代目标出现的形式化结构:
-
{fieldname!coversionflag:formatspec}
-
- fieldname是指定参数的一个数字或关键字,后面跟着可选的“.name”或“[index]”成分引用
- conversionflag可以是r、s或者a分别是在该值上对repr、str或ASCII内置函数的一次调用
- formatspec制定了如何表示该值,包括字段宽度、对其方式、补零、小数点精度等细节,并且以一个可选的数据类型编码结束
- 冒号后的formatpsec组成形式上的描述如下:(方括号表示可选的组成,并且不能编写为常量)
[[fill]align][sign][#][0][width][.precision][typecode]
-
- align可能是<、>、=或者^,分别表示左对齐、右对齐、一个标记符号后的补充或居中对其
- formatspec也包含嵌套的、只带有{}的格式化字符串,它从参数列表动态地获取值(与格式化表达式中的*很相似)
- 格式化还允许一个“b”类型编码用来以二进制格式显示整数(它等同于使用bin内置函数)
- 允许一个“%”类型编码来现实百分比
- 使用唯一的“d”表示十进制的整数(而不是“i”或“u”)
>>> '{0:10} = {1:10}'.format('spam', 123.4567)
'spam = 123.4567'
-
- {0:10}意味着一个10字符宽的字段中的第一个位置参数
- 0代表format的第一个元素,也可以是关键字
- 10代表宽度,不足地方用空格补充
- {0:10}意味着一个10字符宽的字段中的第一个位置参数
>>> '{0:>10} = {1:<10}'.format('spam',123.4567)
' spam = 123.4567 '
-
- {1:<10}意味着第2个位置参数在一个10字符宽度字段中左对齐
>>> '{0.platform:>10} = {1[item]:<10}'.format(sys, dict(item='laptop'))
' darwin = laptop '
-
- {0.platform:>10}意味着第一个参数的platform属性在10字符宽度的字段中右对齐
- 在格式化方法调用中,浮点数支持与%表达式中相同的类型代码和格式化声明
>>> '{0:e},{1:.3e},{2:g}'.format(3.14159,3.14159,3.14159)
'3.141590e+00,3.142e+00,3.14159'
>>> '{0:f},{1:.2f},{2:06.2f}'.format(3.14159,3.14159,3.14159)
'3.141590,3.14,003.14'
-
- 格式化方法也支持十六进制、八进制和二进制格式
- 实际上,字符串格式化是把整数格式化为指定的进制的某些内置函数的替代方法
- 格式化方法也支持十六进制、八进制和二进制格式
>>> '{0:X}, {1:o}, {2:b}'.format(255, 255, 255)
'FF, 377, 11111111'
>>> bin(255),int('11111111', 2), 0b11111111
('0b11111111', 255, 255)
>>> hex(255), int('ff', 16), 0xff
('0xff', 255, 255)
>>> oct(255), int('377', 8), 0o377
('0o377', 255, 255)
-
- 格式化参数可以在格式化字符串中硬编码,或者通过嵌套的格式化语法从参数列表动态地获取,后者很像是格式化表达式中的星号语法
>>> '{0:.2f}'.format(1/3.0)
'0.33'
>>> '%.2f' % (1/3.0)
'0.33'
>>> '{0:.{1}f}'.format(1/3.0, 4)
'0.3333'
>>> '%.*f' % (4, 1/3.0)
'0.3333'
-
- 一种新的内置format函数,它可以用来格式化一个单独的项
- 它是一种更简洁的替代方法,并且大致类似于用%格式化表达式来格式化一个单独的项
- 一种新的内置format函数,它可以用来格式化一个单独的项
>>> '{0:.2f}'.format(1.2345)
'1.23'
>>> format(1.2345, '.2f')
'1.23'
>>> '%.2f' % 1.2345
'1.23'
与%格式化表达式比较
-
-
- 对于未知的引用和字典键,字符串格式化方法看上去和%格式化表达式很像
- 特别是提前使用类型代码和额外的格式化语法
- 实际上,在通常的情况下,格式化表达式可能比格式化方法调用更容易编写
- 特别是当使用通用的%s打印字符串替代目标的时候
- 对于未知的引用和字典键,字符串格式化方法看上去和%格式化表达式很像
-
>>> print('%s = %s' % ('spam', 42))
spam = 42
>>> print('{0} = {1}'.format('spam', 42))
spam = 42
-
- 更复杂的格式化倾向于降低复杂性,格式化方法还提供了一些潜在的优点
- 最初的%表达式无法处理关键字、属性引用和二进制类型代码
- 尽管%格式化字符串中的字典键引用常常能够达到类似的目标
- 更复杂的格式化倾向于降低复杂性,格式化方法还提供了一些潜在的优点
为什么用新的格式化方法
-
-
- 拥有%表达式没有的一些额外功能
- 可以更明确地进行替代值引用
- 考虑到操作符会有一个更容易记忆的方法名
- 不支持用于单个和单个替代值大小写的不同语法
-
通常意义下的类型分类
-
-
- 同样分类的类型共享其操作集合
- Python中的三个主要类型(以及操作)的分类:
- 数字(整数、浮点数、二进制、分数等)
- 支持加法和乘法等
- 序列(字符串、列表、元组)
- 支持索引、分片和合并等
- 映射(字典)
- 支持通过键的索引等
- 集合是自成一体的一个分类(不会把键映射到值,也不会逐位的排序顺序)
- 可变类型能够在原处修改
- 不可变类型(数字、字符串、元组、不可变集合)
- 可以通过运行表达式来创建新的对象并将其结果分配给变量
- 可变类型(列表、字典、可变集合)
- 可以通过操作原处修改,不用创建新的对象,同时也可以复制
- 不可变类型(数字、字符串、元组、不可变集合)
- 同样分类的类型共享其操作集合
-