1-4-字符串
1. 字符串基础
Python字符串是一个有序的字符的集合,被划分为不可变序列(immutable sequence)这一类别,用来存储和表现基于文本的信息。
在Python 3.x中有三种字符串类型:
- str:用于Unicode文本(包括ASCII)
- bytes:用于二进制数据(包括已编码文本)
- bytearray:是bytes的一种可变的变体
文件在两种模式下工作:
- text:内容为str格式,执行Unicode编码
- binary:处理原始bytes数据,不进行数据编译
常见字符串常量和表达式:
S = '' #空字符串
S = "spam's" #双引号和单
S = 's\np\ta\x00m' #转义序列
S = '''...多行字符串...''' #三重引号字符串块
S = r'\temp\spam' #Raw字符串引号相同(无转义)
B = b'sp\xc4m' #字节字符串
U = u'sp\u00c4m' #Unicode字符串
S1 + S2 #合并(concatenate)
S * 3 #重复
S[i] #索引
S[i:j] #分片(slice)
len(S) #求长度
"a %s parrot" % kind #字符串格式表达式
"a {0} parrot".format(kind) #字符串格式化方法
S.find('pa') #字符串方法调用:搜索
S.rstrip() #移除空格
S.replace('pa', 'xx') #替换
S.split(',') #用分隔符(delimiter)分割
S.isdigit() #内容测试
S.lower() #字体转换
S.endswith('spam') #结束测试
'spam'.join(strlist) #插入分隔符
S.encode('latin-1') #Unicode编码
B.decode('utf8') #Unicode解码
for x in S: print(x) #迭代
'spam' in S
[c * 2 for c in S]
map(ord, S) #成员关系
2. 字符串常量
字符串的编写方式有很多:
- 单引号:
'spa"m'
- 双引号:
"spa'm"
- 三引号:
'''…spam…''',"""…spam…"""
- 转义字符:
"s\tp\na\0m"
- Raw字符串:
r"C:\new\test.spm"
- bytes字符串:
b'sp\x01am'
- Unicode字符串:
u'eggs\u0020spam'
最常见的是单引号和双引号,使用两种引号可以不使用反斜杠转义字符就可以实现在一个字符串中包含其余种类的引号。
"knight's",'knight"s'
("knight's", 'knight"s')
Python会自动在任意的表达式中合并相邻的字符串常量,也可以简单地在它们之间增加+操作符来明确地表示这是一个合并操作。
"Meaning "'of'" Life"
'Meaning of Life'
在字符串中间增加逗号会创建一个元组,而不是一个字符串。Python 倾向于以单引号打印字符串,除非字符串内已有单引号。
'knight\'s',"knight\"s"
("knight's", 'knight"s')
2.1 转义序列(Escape sequences)
转义序列可以在字符串中嵌入不容易通过键盘输入的字节。
转义序列以反斜杠 \ 开头,后面接一个或多个字符,在最终的字符串对象中会被一个单个字符替代。
字符串反斜杠字符:
转义 | 意义 |
---|---|
\newline | 忽视(连续换行) |
|反斜杠(保留\) | |
' | 单引号(保留') |
" | 双引号(保留") |
\a | 响铃 |
\b | 退格 |
\f | 换页(formfeed) |
\n | 换行 Newline(linefeed) |
\r | 返回 |
\t | 水平制表符 |
\v | 垂直制表符 |
\N | Unicode数据库ID |
\uhhhh | Unicode 16位的十六进制值 |
\Uhhhhhhhh | Unicode 32位的十六进制值 |
\xhh | 十六进制值hh |
\ooo | 八进制值ooo |
\0 | Null:二进制0字符(不是字符串结尾) |
\other | 不转义(保留 \ 和other) |
Python以十六进制显示非打印的字符。
s = '\001\001\x03'
s
'\x01\x01\x03'
2.2 raw 字符串抑制转义
当字母 r(大写或小写)出现在字符串的第一个引号前则该字符串为一个 raw 字符串,raw 字符串会关闭转义机制,raw 字符串还可用于正则表达式。
raw 字符串不能以单个的反斜杠结尾,若要用单个反斜杠结束一个 raw 字符串,有如下两个办法:
- 用两个反斜杠并切片掉第二个反斜杠:
r'1\nb\tc\\'[:-1]
- 手动添加一个反斜杠:
r'1\nb\tc' + '\\'
2.3 三重引号编写多行字符串块
又称块字符串,可以编写多行文本数据,以三重引号开始(单引号和双引号都可以),并紧跟任意行数的文本,再以开始时同样的三重引号结尾。
mantra = """Always look
on the bright
side of life."""
mantra
'Always look\n on the bright\nside of life.'
print(mantra)
Always look
on the bright
side of life.
三重引号字符串会保留所有引号内的字符串,包括代码右侧的注释,所以不要在引号内添加注释。
三重引号字符串常用于文档字符串,当它出现在文件的特定地点时,将被当作注释一样的字符串常量。
三重引号字符串还可用于临时废除一些代码,对于大段的代码,这比手动在每一行之前加入 # 号,之后再删除它们要容易得多。
x = 1
"""
import os
print(os.getcwd())
"""
y = 2
3. 实际应用中的字符串
3.1 基本操作
s = 'spam''eggs''food'
print(s)
spameggsfood
s = 'spam' + 'eggs' + 'food'
print(s)
spameggsfood
'Ni!' * 4
'Ni!Ni!Ni!Ni!'
myjob = 'hacker'
for c in myjob:
print(c, end=' ')
h a c k e r
'k' in myjob
True
'spam' in 'abcspamdef' # 子字符串搜索
True
3.2 索引和分片
字符串中的字符通过索引提取。
Python 支持使用负偏移获取元素。
s = 'spam'
s[0], s[-2] # 索引
('s', 'a')
s[1:3], s[1::2], s[::-1] # 分片
('pa', 'pm', 'maps')
分片左边偏移作为下边界(包含),右边偏移作为上边界(不包含)。
扩展分片:第三个限制值
分片表达式的第三个索引用作步进,默认为 1。
S = 'abcdefghijklmnop'
S[1:10:2]
'bdfhj'
S[::2]
'acegikmo'
S[::-1]
'ponmlkjihgfedcba'
S[5:1:-1]
'fedc'
3.3 字符串转换工具
可以用 int,float 函数将字符串转换为数字或浮点数。str 函数可以将数字转换为字符串表达式。
int('22') + 32
54
str(33.0) + '2'
'33.02'
float('1.5')
1.5
字符串代码转换
单个字符可以通过将其传给内置的 ord 函数转换为其对应的 ASCII 码。chr 函数执行相反的操作。
ord('a')
97
chr(120)
'x'
S = '5' # 可以预先将当前字符串转换为整型并进行数学运算生成下一个字符
S = chr(ord(S) + 1)
S
'6'
3.4 修改字符串
字符串是不可变对象,不能在原地修改字符串:
S = 'spam'
S[0] = 'x'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-24-7ffb2cc33b47> in <module>()
1 S = 'spam'
----> 2 S[0] = 'x'
TypeError: 'str' object does not support item assignment
要改变一个字符串,需要利用合并、分片这样的工具来建立并赋值给一个新的字符串。
S = S + 'SPAM!'
S
'spamSPAM!'
S = S[:4] + 'Burger' + S[-1]
S
'spamBurger!'
S = 'splot'
S = S.replace('pl', 'pamal')
S
'spamalot'
可以通过字符串格式化表达式来创建新的文本值。
'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!'
4. 字符串方法
4.1 修改字符串
S = 'spammy'
S = S.replace('mm', 'xx')
S
'spaxxy'
S = 'xxxxSPAMxxxxSPAMxxxx'
S.replace('SPAM', 'EGGS') # 替换所有
'xxxxEGGSxxxxEGGSxxxx'
S.replace('SPAM', 'EGGS', 1) # 替换一个
'xxxxEGGSxxxxSPAMxxxx'
S = 'spammy'
L = list(S)
L
['s', 'p', 'a', 'm', 'm', 'y']
L[3] = 'x'
S = ''.join(L)
S
'spaxmy'
'SPAM'.join(['eggs', 'sausage', 'ham'])
'eggsSPAMsausageSPAMham'
4.2 文本解析
line = 'aaa bbb ccc'
cols = line.split()
cols
['aaa', 'bbb', 'ccc']
line = 'bob,hacker,40'
line.split(',')
['bob', 'hacker', '40']
4.3 其他常见字符串方法
line = 'The knights who say Ni!\n'
line.rstrip()
'The knights who say Ni!'
line.upper()
'THE KNIGHTS WHO SAY NI!\n'
line.isalpha()
False
line.endswith('Ni!\n')
True
line.startswith('The')
True
line.find('Ni') # 搜索
20
'Ni' in line
True
5. 字符串格式化表达式
字符串格式化允许在一个单个的步骤中对一个字符串执行多个特定类型的替换。
Python 中的字符串格式化可以以三种形式实现:
- 字符串格式化表达式:
'…%s…'%(values)
从 Python 诞生的时候就有的最初的技术,基于 C 语言的“printf”模型,并且在大多数现有代码中使用。 - 字符串格式化方法调用:
'…{}…'.format(values)
Python 独有的方法,并且和字符串格式化表达式功能有很大的重叠。 - 使用特殊的
{}
序列,将想要打印的变量放入{}
中,字符串以 f 字母开始,即f"Hello {somevar}"
。
5.1 格式化表达式
Python 在对字符串操作的时候定义了 % 二进制操作符,% 提供了简单的方法对字符串的值进行格式化,这一操作取决于格式化定义的字符串。
- 在 % 操作符的左侧放置一个需要进行格式化的字符串,这个字符串带有一个或多个嵌入的转换目标,都以 % 开头(例如,% d)。
- 在 % 操作符右侧放置一个(或多个,嵌入到元组中)对象,这些对象将会插入到左侧想让 Python 进行格式化字符串的一个(或多个)转换目标的位置上去。
%s 表示把它们都转换成字符串,一般只需用 %s,格式化总是会返回新的字符串作为结果而不是对左侧的字符串进行修改。
"%s -- %s -- %s"%(42, 3.1415, [1, 2, 3])
'42 -- 3.1415 -- [1, 2, 3]'
5.2 更高级的字符串格式化表达式
对更高级的特定类型的格式化来说,可以使用格式化表达式中列出的任何一个转换代码。
字符串格式化代码
代码 | 意义 |
---|---|
s | 字符串(或任何对象) |
r | s,但使用 repr,而不是 str |
c | 字符 |
d | 十进制(整数) |
i | 整数 |
u | 无号(整数) |
o | 八进制整数 |
x | 十六进制整数 |
X | x,但打印大写 |
e | 浮点指数 |
E | e,但打印大写 |
f | 浮点十进制 |
F | 浮点十进制 |
g | 浮点 e 或 f |
G | 浮点 E 或 F |
% | 常量 % |
在格式化字符串中,表达式左侧的转换目标支持多种转换操作,通用结构为:%[(keyname)][flags][width][.precision]typecode
typecode 为格式化表达式转换代码,在 % 和字符码之间,可以进行以下任何操作:
- 放置一个字典的键
- 罗列出左对齐(-)、正号(+)、正数前补空格负数前补 - (一个空格)和补零(0)的标志位
- 给出数字的整体长度和小数点后的位数
width 和 precision 都可以编码为一个 *,以指定它们应该从输入值的下一项中取值
x = 1.23456
a = "%d...|%-6d...|%06d"%(x, x, x)
b = '%e | %E | %f | %F | %g | %G'%(x, x, x, x, x, x)
c = '%-6.2f | %05.2f | %+06.1f'%(x, x, x)
d = '%f, %.2f, %.*f'%(1/3.0, 1/3.0, 4, 1/3.0)
print(a)
print(b)
print(c)
print(d)
1...|1 ...|000001
1.234560e+00 | 1.234560E+00 | 1.234560 | 1.234560 | 1.23456 | 1.23456
1.23 | 01.23 | +001.2
0.333333, 0.33, 0.3333
5.3 基于字典的字符串格式化
'%(n)d %(x)s'%{'n':1, 'x':'spam'}
'1 spam'
格式化字符串里(n)和(x)引用右边字典中的键,并提取它们相应的值。
常与内置函数 vars 配合使用,这个函数返回的字典包含了所有在本函数调用时存在的变量。
food = 'fish'
age = 40
vars()
'%(age)d %(food)s'%vars()
'40 fish'
6. 字符串格式化调用方法
format 方法使用主体字符作为模板,接受任意多个表示将要根据模板替换的值的参数。
在主体字符串中,花括号通过位置、关键字或者相对位置指出替换目标及将要插入的参数。
6.1 基础知识
template = '{0}, {1} and {2}' # 通过位置
template.format('spam', 'ham', 'eggs')
'spam, ham and eggs'
template = '{motto}, {pork} and {food}' # 通过关键字
template.format(motto = 'spam', pork = 'ham', food = 'eggs')
'spam, ham and eggs'
template = '{motto}, {0} and {food}' # 通过两者
template.format('ham', motto = 'spam' , food = 'eggs')
'spam, ham and eggs'
template = '{}, {} and {}' # 通过相对位置
template.format('spam', 'ham', 'eggs')
'spam, ham and eggs'
6.2 高级格式化方法语法
对于格式化方法,在替换目标的标识之后使用一个冒号,后面跟着可以指定字段大小、对齐方式和一个特定类型编码的格式化声明:{fieldname component !conversionflag :formatspec}
- fieldname 标识参数的可选数字或关键字,在使用相对参数编号时可以省略
- component 一个由零个或多个
.name
或[index]
引用组成的字符串,用于获取参数的属性和索引值,在使用完整参数值时可以省略这些引用。 - conversionflag 以 ! 开头,可以是 r、s、或者 a,分别是该值上对 repr、str 或 ascii 内置函数的一次调用。
- formatspec 以 : 开头,指定了如何表示该值,包括字段宽度、对齐方式、补零、小数点精度等,并且以一个可选的数据类型编码结束。
formatspec 组成形式如下:
[[fill]align][sign][#][0][width][,][.precision][typecode]
fill 可以是任意填充字符除了 { 或 };
align 可能是 <、>、= 或 ^,分别表示左对齐、右对齐、一个标记字符后的补充或居中对齐;
sign 可以是 +、- 或空格;
,(逗号)选项为千位分隔符请求逗号;
width 和 precision 和 % 表达式中一样。
6.3 高级格式化方法
例如,下面的 {0:10} 意味着一个 10 字符宽的字段中的第一个位置参数,{1:<10} 意味着第 2 个位置参数在一个 10 字符宽度字段中左对齐,{0.platform:>10} 意味着第一个参数的 platform 属性在 10 字符宽度的字段中右对齐:
'{0:10} = {1:10}'.format('spam', 123.4567)
'spam = 123.4567'
'{0:>10} = {1:<10}'.format('spam', 123.4567)
' spam = 123.4567 '
import sys
'{0.platform:>10} = {1[kind]:<10}'.format(sys, dict(kind='laptop'))
' win32 = laptop '
可以省略参数数字。
'{:10} = {:10}'.format('spam', 123.4567)
'spam = 123.4567'
{2:g} 表示第三个参数默认根据 "g" 浮点数表示格式化,{1:.2f} 制定了带有 2 个小数位的 "f" 浮点数格式,{2:06.2f} 添加一个 6 字符宽度的字段并且在左边补充 0:
'{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'
格式化参数可以在格式化字符串中硬编码,或者通过嵌套的格式化语法从参数列表动态地获取:
'{0:.2f}'.format(1 / 3.0)
'0.33'
'{0:.{1}f}'.format(1 / 3.0, 4)
'0.3333'
7. 通常意义下的类型分类
7.1 同样分类的类型共享其操作集合
在 Python 中有三个主要类型(以及操作)的分类:
- 数字(整数、浮点数、二进制、分数等)
支持加法和乘法等。 - 序列(字符串、列表、元组)
支持索引、分片和合并等 - 映射(字典)
支持通过键的索引等 集合是自成一体的一个分类(它们不会把键映射到值,也没有逐位的排序序列)。
7.2 可变类型能够在原处修改
Python 中的主要核心类型划分为如下两类:
- 不可变类型(数字、字符串、元组、不可变集合)
不可变的分类中没有哪个对象类型支持原处修改,尽管我们总是可以运行表达式来创建新的对象并将其结果分配给变量。 - 可变类型(列表、字典、可变集合)
可变类型总是可以通过操作原处修改,而不用创建新的对象。
新字符串格式方法
var = 'spam'
print(f"the string is {var}")
the string is spam