细谈字符串及其格式化表达式
字符串是python中一个极为重要的数据类型,他的功能十分强大,应用也十分广泛,它可以表示符号和词语、载入到文本文件中作为内容、Internet网址和python程序,它是python中极为重要的处理工具集。
字符串常量
字符串常量使用起来极其简单方便,唯一差强人意可能是他的编写方式多种多样:
单引号:'jeff"D';
双引号:"jeff'D";
三引号:'''jeffD''',"""jeffD""";
转义字符:"j\teff\nD";
Raw字符串:r"C:\new\test.py";
还有bytes类型与Unicode类型字符串:b'jeffD',u'jeffD';
对于python中字符串的引用,单双引号并没有强引用弱引用的概念,他们是可以互换的,代表同一种意思,之所以有这两种方式是因为可以简化一些需要转义的字符串,例如:'jef\'D'简化为'jef"D',代码更为简洁易懂。
转义序列代表特殊字节
反斜杠用来做转义字符在很多地方都在使用,同样这也应用在字符串常量中。\跟一到多个字符,在python解释器会被单个字符代替,这个字符通过转义序列定义一个二进制值。
print(len('jeff\tD\n')) 运行结果: 6
这里\t与\n都只作为一个字符。python中有一整套的转义字符序列。
\newline 忽视(连续)
\\ 反斜杠(即\)
\' 就是'
\" 就是"
\a 响铃
\b 倒退
\f 换页
\n 换行
\r 返回
\t 空格制表符
\v 垂直制表符
\N{id} Unicode数据库id
\uhhhh Unicode16位16进制值
\Uhhhhhhhh Unicode32位16进制值
\xhh 十六进制值
\ooo 八进制值
\0 Null(不会结束字符串)
\other 保留
如果\后面跟的不是一个可转义字符,就会以\的形式出现在最终的字符串里。
print('jef\D') 运行结果: jef\D
有些时候我们希望\在字符串中不进行转义,这个时候就用到raw字符串抑制转义。
print("C:\new\test.py") print(r"C:\new\test.py") 运行结果: C: ew est.py C:\new\test.py
raw字符串在这里的作用就是关闭转义机制。我们还可以用另一种方法,就是使用两个\代替一个\。
print("C:\\new\\test.py") 运行结果: C:\new\test.py
值得注意的是,即使是raw字符串也不可以使用\结尾,\会转义后续引用的字符。也就是说r"...\"不是一个有效的字符串。并且奇数个\也不是有效的字符串常量。
有三种方式可以解决奇数个字符串常量的方法:
print(r"C:\new\test\\"[:-1]) print("C:\\new\\test\\") print(r"C:\new\test"+'\\') 运行结果: C:\new\test\ C:\new\test\ C:\new\test\
三重引号的字符串
三引号字符串也称作块字符串,可以操作任意多行的字符串,在程序需要输入多行文本的时候,比如在源文件中编写HTML或XML代码,直接使用这样的块字符串代替外部文本是极为方便的。并且他还长长用来做注释使用,当我们需要多行做注释时,有些工具不能使用快捷方式进行多行#时,这种方法显得尤为简便。不仅是注释,某些时候我们需要取消一些代码时也可以使用这种方法隐去不需要的代码。
字符串基本操作
首先,必须明确的一点是,字符串是一个不可变数据类型,我们所做的一切操作都没有改变原始的字符串,只是开辟出新的空间存放改变后的字符串,并且将变量指向新的字符串,我们肉眼所看到的觉得是字符串变了,其实底层的字符串并没有变化。这在操作字符串时一定要切记。
a='asdfg' b='adf' c='sdf' print(b in a) print(c in a) 运行结果: False True
在字符串中操作符重载发生作用,+与*在字符串在的操作为字符串拼接和重复的意思。与in判断类似的是find方法,in返回布尔值,而find方法会返回索引值,找不到则会报错。
同时字符串也是可迭代对象,我们可以使用for循环遍历它。
字符串的索引与切片
和所有有序类型一样,字符串也支持索引很切片的操作。python的索引支持负偏移方法从序列中获取元素,并且负偏移和字符串长度相加就是这个元素的正偏移量。我们简单的人为是从结束处倒着计数即可。
字符串切片使用冒号分割偏移索引字符串中连续的内容返回新的值。
索引:
1.第一个元素的偏移量为0;
2.负偏移意味着从右往左计数;
3.S[0]获取第一个元素;
4.S[-2]与S[len(S)-2]是同一个元素。
切片:
1.S[i:j:k]i与j是偏移量,k是步进,i与j默认是0和len(S);
2.S[1:3]指从偏移为1的元素,到但不包括3的元素;
3.S[1:]表示偏移为1到末尾之间的元素;
4.[:3]表示从开始到不包括索引为3之间的元素;[:-1]整个字符串的元素,除了最后一个元素以外的所有;
5.[:]顶层拷贝,整个字符串。
当步进为负数的时候表示从右往左,实际效果就是反转此序列。
name= 'jeffD' print(name[::-1]) 运行结果: Dffej
切片时常使用在读取文件内容时,字符串使用‘\n’换行符结尾,line[:-1],就可以提取本行内容。除此之外还可以使用strip方法。
字符串转换工具
之前在整形常量中也介绍了+在数字类型中做数学加法计算,而在字符串中做拼接符号使用。那么我想要让字符串和数字使用+,必然会导致一个错误,我们如果需要这样做就需要使用到字符串转换工具,让他们具有相同的类型然后操作。
print(1+'11') 运行结果: print(1+'11') TypeError: unsupported operand type(s) for +: 'int' and 'str'
print(str(1)+'11') print(1+int('11')) 运行结果: 111 (str) 12 (int)
当然我们还可以使用eval()函数来完成这项操作。
print(1+eval('11')) 运行结果: 12
ord()函数可以将str转换成对应的ASCII码,chr()执行相反操作,将ASCII码转化为对应的字符。
下面是此函数的应用,将二进制转化为十进制。
i=0 b='1011' while b!='': i=i*2 +(ord(b[0])-ord('0')) b=b[1:] print(i) 运行结果: 11
字符串常用方法
首先方法特定于对象类型,所以字符串方法只适用于字符串类型。
replace()方法:
a='jeff' print(a.replace('ff','dd')) 运行结果: jedd
replace()方法等同于:
a='jeff' print(a[0:2]+'dd') 输出结果: jedd
a='jeff' print(a.replace('f','d',1)) 运行结果: jedf
find()方法:
a='jeff' print(a.find('f')) 运行结果: 2
join方法:
a='jeff' print(','.join(list(a))) 运行结果: j,e,f,f
在文本解析的过程中需要使用到方法,首先文本解析就是要通过切片从原字符串中分离出我们想要的内容。
a='jeff,boy,cool' print(a.split(',')) print(a.split(',')[0]) 运行结果: ['jeff', 'boy', 'cool'] jeff
除此之外,字符串还有很多方法,这里就不一一列举了,在之前的学习里也学习了很多相关的方法,多用自然就会了。
字符串格式化
字符串格式化允许在一个单个步骤中对一个字符串进行多个特定类型替换。目前有两种格式化实现方式:1.字符串格式化表达式;2.字符串格式化方法调用。
字符串格式化表达式:
在字符串表达式中我们使用%作为操作符,在%的左侧放置需要进行格式化的字符串,字符串中包括至少一个嵌入目标(%[d]类型存放),在%的右侧放置需要嵌入的对象本体,此对象会代替左侧的嵌入目标。
a='name is %s,age is %d'%('jeff',111) print(a) 运行结果: name is jeff,age is 111
字符串格式化代码:
格式化符号 |
意义 |
%c |
转换成字符(ASCII 码值,或者长度为一的字符串) |
%r |
优先用repr()函数进行字符串转换 |
%s |
优先用str()函数进行字符串转换 |
%d / %i |
转成有符号十进制数 |
%u |
转成无符号十进制数 |
%o |
转成无符号八进制数 |
%x / %X |
转成无符号十六进制数(x / X 代表转换后的十六进制字符的大小写) |
%e / %E |
转成科学计数法(e / E控制输出e / E) |
%f / %F |
转成浮点数(小数部分自然截断) |
%g / %G |
%e和%f / %E和%F 的简写 |
%% |
输出% (格式化字符串里面包括百分号,那么必须使用%%) |
表达式的左侧的嵌入目标支持多种操作,但是转换目标语法却非常严谨,转换的目标语法标准为:%[(name)][flags][width][.precision]typecode。
%和转化符号之间还可以添加各种操作:放置字典的键;罗列左对齐(-),正负号(+)和补零(0)的标志位;给出数字整体长度和小数点后的位数等。width和percision都可以编码一个*,指定他们应该从输入值的下一项取值。
print('name is %s,%d'%('jeff',111)) print('name is %-6s,%-6d'%('jeff',111)) print('name is %06s,%06d'%('jeff',111)) print('name is %+6s,%+6d'%('jeff',111)) 运行结果: name is jeff,111 name is jeff ,111 name is jeff,000111 name is jeff, +111
a=3.1415926 print('%e'%a) print('%f'%a) print('%g'%a) print('%-6.2f'%a) print('%06.2f'%a) print('%+06.2f'%a) print('%.*f'%(4,a)) 运行结果: 3.141593e+00 3.141593 3.14159 3.14 003.14 +03.14 3.1416
可以指定通过计算得出width和precision。
基于字典的字符串格式化
将%右边写成字典,提取其中的值。这在生成类似HTML或XML程序中经常会利用到这一技术。
print('name is %(name)s,age is %(age)d'%{'name':'jeff','age':111}) 运行结果: name is jeff,age is 111
字符串格式化调用方法:
format方法使用主体字符串作为模板,并且接收任意多的要与模板替换的值得参数。主体字符串中,花括号通过位置{1}或{name}指出替换目标及将要插入的参数。
print('name is {0},age is {1}'.format('jeff',111)) 输出结果: name is jeff,age is 111
print('name is {name},age is {age}'.format(name='jeff',age=111)) 输出结果: name is jeff,age is 111
print('name is {0},age is {age}'.format('jeff',age=111)) 运行结果: name is jeff,age is 111
format方法还有更为复杂的操作来支持高级用途。
import sys a='my {1[spam]} runs {0.platform}'.format(sys,{'spam':'computer'}) print(a) 运行结果: my computer runs win32
import sys a='my {config[spam]} runs {sys.platform}'.format(sys=sys,config={'spam':'computer'}) print(a) 运行结果: my computer runs win32
格式化字符串中[]中指定了字典的键,点表示相关字符串引用的一项对象属性。[]中还可以指定列表等序列偏移量的索引,这种方式只有单个正偏移才有效。这种方式要想使用负偏移或分片或者其他方式都必须在字符串方法格式化进行之前完成。
a=[1,2,3] print('1={0[0]},2={0[1]},3={0[2]}'.format(a)) 运行结果: 1=1,2=2,3=3
a=[1,2,3] print('1={0},2={1},3={2}'.format(a[0],a[1],a[2])) 运行结果: 1=1,2=2,3=3
a=[1,2,3] b=a[0],a[-2],a[0:2] print('1={0},2={1},3={2}'.format(*b)) 运行结果: 1=1,2=2,3=[1, 2]
除了上述我们还添加了额外的语法来实现层级。即在目标标识后使用冒号后面再指定字段大小、对齐方式和一个特定类型的编码的格式化声明。
格式化字符串语法:{fieldname:conversionflag:formatspec},其中fieldname是指定参数的一个数字或关键字,后面跟可选的.name或[index],conversionflag为r、s、a分别在该值对应reper、str、ascii内置函数调用,formatspec指定该值的字段宽度、对齐方式、补零、小数点精度等。
formatspec的组成描述:[[fill]align][sign][#][0][width][.precision][typecode]
其中align用<,>,=,^,分别表示左对齐,右对齐,一个标记字符后补充、居中对齐。formatspec包含带嵌套,只带有{}的格式化字符串。{0:10}表示第一个参数位宽10字符,{1:<10}表示第二个参数位宽10字符并且左对齐。{0.platform:>10}表示第一个参数platform属性在10字符位宽的字段右对齐。
print('{0:10} ={1:<10}'.format('jeff',111.11)) 运行结果: jeff =111.11
{2:g}第三个参数根据‘g’浮点数操作,{1:.2f}则是两位小数的‘f’浮点数,{2:06.2f}表示第二个参数添加为6个字符宽度字段并在左侧补充0两位小数的‘f’浮点数。当然方法格式化也支持二进制,八进制,十六进制。
方法格式化的小补充:
print('{0:.{1}f}'.format(1/3.0,4)) 运行结果: 0.3333
print(format(1/3,'.2f')) 运行结果: 0.33
两种格式化方法的比较
格式化表达式:
1.相比于格式化方法调用更为简单,更为简练;
2.在以后的版本可能会被删除;
格式化方法:
1.处理关键字,属性引用,二进制代码更为方便。
2.虽然复杂,但是拥有很多高级功能,这是格式化表达式没有的功能;
3.在替代值引用方面更明确;
4.考虑操作符会有一个更容易记忆的方法名;
5.不支持单个或多个替代值大小写的不同语法。
本文是在阅读完python学习手册后进行的简单整理,如有知识性错误,请各位大神帮忙指正。