1. 字符串简述
目前对于程序员来说,Unicode是一个非常重要的知识点.对于Python3.X以上的版本,字符串就是Unicode(用str函数来操作),但是对于Python2.7X以上的版本,str函数处理的是ASCII字符.(ASCII只是Unicode的一个子集),以下是不同版本的Python对字符串的处理:
1. 在Python3.X中有三种字符串类型:str用于Unicode(包含ASCII),bytes用于二进制数据(包含编码的文本),bytearray是可改变的bytes类型.
文件有两种模型:str实现Unicode编码,而二进制处理bytes类型,而不涉及任何的转换.
2. 在Python2.X中,"unicode"字符串代表Unicode文本,str处理八位文本和二进制数据,bytearray在2.6中有效而且在3.X中成为一部分.
文件中str用来处理简单的字符串文本,而codecs模块支持Unicode文本,用于其编解码.
1. String Basics
对于Python来说,字符串实际上就是不可改变的字符序列,这也意味着它可迭代.
S = ' ' | 空字符串 |
S = "spam's" | 单双引号作用一样 |
S = 's\np\ta\x00m' | 转义符序列 |
S = """...multiline""" | 三引号区域字符串 |
S = r''\temp\spam | 原始字符串(转移字符不进行转移) |
S = b'sp\xc4m' | byte字符串 |
S = u'sp\uooc4m' | Unicode字符串 |
S1 + S2 | 字符串连接 |
S * 3 | 字符串重复 |
S[i] | 字符串索引 |
S[i:j] | 字符串分割 |
len(S) | 字符串长度 |
"a %s parrot" % kind | 字符串格式化表示 |
"a {0} parrot".format(kind) | 字符串格式化表示的方法 |
S.find('pa') | 字符串查询 |
S.rstrip() | 去除空白符 |
S.replace('pa', 'xx') | 字符串替换 |
S.split(',') | 字符串分割 |
S.isdigit() | 判断是否为十进制 |
S.lower() | 转换为小写 |
S.endswith('spa,') | 尾部字符串测试 |
'spam'.join(strlist) | 将列表以'spam'作为分隔符转换为字符串 |
S.encode('latin-1') | Unicode编码 |
B.decode('utf8') | Unicode解码 |
for x in S: print(x) | 可迭代 |
'spam' in s | 判断'spam'是否在S中 |
[c * 2 for c in S] | 列表推导式 |
map(ord, S) | map函数 |
re.match('sp(.*)am', line) | 正则表达式对字符串的运用 |
2. Single-and Double-Quoted Strings Are the Same
对于Python来说,单双字符串是一样的.但是单引号字符串可内嵌于双引号字符串中(双引号字符串也可内嵌于单引号字符串中):
>>> 'shrubbery', "shrubbery"
('shrubbery', 'shrubbery')
>>> 'knight"s', "knight's"
('knight"s', "knight's")
备注:
1. 一般都是单引号在双引号字符串中,而很少有双引号字符在单引号字符串中.
2. 这里逗号是重要的,它起到元组的作用.如果去掉逗号,则字符串会自动拼接:
>>> title = "Meaning " 'of' " Life"
>>> title
'Meaning of Life'
3. Escape Sequences Represent Special Characters
以分隔符"\"开始的为转移字符(后跟有意义的转移字符,而非无效的字符,如\n代表换行,而\p则代表字符串"\p").对于转移字符,实际上存储一个二进制的值:
>>> s = 'a\nb\tc'
>>> s
'a\nb\tc'
>>> print(s)
a
b c
>>> len(s)
5
所有的转义格式如下:
\\,\',\",\a,\b,\f,\n,\r,\t,\v | 基本转义字符 |
\xhh | 十六进制值 |
\ooo | 八进制值 |
\0 | Null:二进制0字符(并不代表字符串的结束,和C语言不一样) |
\N{ id } | Unicode数据库ID |
\uhhhh | Unicode字符(16位十六进制值) |
\Uhhhhhhhh | Unicode字符(32位十六进制值) |
\other | 非转义字符 |
在python中,通常可内嵌二进制的值(内部表示为十六进制显示):
>>> s = 'a\0b\0c'
>>> s
'a\x00b\x00c'
>>> len(s)
5
>>> s = '\001\002\003'
>>> s
'\x01\x02\x03'
>>> len(s)
3
但是对于字符串来说,如果"\"后跟无效的转移字符,则"\"就直接被表示为一个字符"\":
>>> x = "C:\py\code"
>>> x
'C:\\py\\code'
>>> len(x)
10
4. Raw Strings Suppress Escapes
但是如果我们不想被转移字符所困恼怎么办?我们可以在字符前面加字母"r":
>>> print("C:\new\test.dat")
C:
ew est.dat
>>> print(r"C:\new\test.dat")
C:\new\test.dat
>>> path = r"C:\new\test.dat"
>>> path
'C:\\new\\test.dat'
>>> len(path)
15
但是对于r来说,"\"却不能出现在末尾:
>>> r"...\"
SyntaxError: EOL while scanning string literal
5. Triple Quotes Code Multiline Block Strings
三引号字符串通常称为"区域字符串":即字符串可存在于多行之中.
不要在三引号字符串中添加注释,这样注释将会成为字符串的一部分.
而三引号字符串通常用于"文档字符串",用于说明一个函数或者一个类的作用.
2. Strings in Action
1. Basic Operations
我们可以使用"+"来连接字符串(因为字符串不可改变,所以我们实际上是新建一个字符串对象),使用"*"来重复字符串.
>>> len('abc')
3
>>> 'abc' + 'def'
'abcdef'
>>> 'Ni!' * 4
'Ni!Ni!Ni!Ni!'
但是Python和JavaScript(因为Python和JavaScript具有可比性)有一点不同之处在于:Python并不会自动进行类型的转换:
>>> 'abc' + 9
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
'abc' + 9
TypeError: cannot concatenate 'str' and 'int' objects
而在JavaScript中,这是合法的.数字9会自动被转换成字符串'9'.
我们可以对字符串进行迭代操作,并且可以通过操作符"in"来判断是否在字符串中:
>>> myjob = "hacker"
>>> for c in myjob:
print(c, end = ' ')
h a c k e r
>>> "k" in myjob
True
>>> "z" in myjob
False
>>> 'spam' in 'abcspamdef'
True
2. Indexing and Slicing
字符串是字符组成的一个不可改变的序列集合,所以我们可以对它进行索引和切片的操作.但是和C语言不一样的一处在于:Python允许负数索引,-1代表最后一个字符,-2代表倒数第二个,依次类推:
>>> S = 'spam'
>>> S[0], S[-2]
('s', 'a')
>>> S[1:3],S[1:],S[:-1]
('pa', 'pam', 'spa')
我们可以给切片增加一个参数:步长(S[i:j:k],k表示一个步长)
>>> S = 'abcdefghijklmnop'
>>> S[1:10:2]
'bdfhj'
>>> S[::2]
'acegikmo'
但是步长也可以是负数,代表递减:
>>> S = 'hello'
>>> S[::-1] #这里等价于S[最尾部索引:0:-1]
'olleh'
>>> S = 'abcdefg'
>>> S[1:5:-1]
''
>>> S[5:1:-1]
'fedc'
而我们也可以使用slice函数来表示切片:
>>> 'spam'[1:3]
'pa'
>>> 'spam'[slice(1, 3)]
'pa'
>>> 'spam'[::-1]
'maps'
>>> 'spam'[slice(None, None, -1)]
'maps'
3. String Conversion Tools
Python会阻止任何产生歧义的转换,因为"+"在Python中既可以作为数值操作的加号,也可以作为字符串的连接,所以以下的操作存在错误:
>>> "42" + 1
Traceback (most recent call last):
File "<pyshell#22>", line 1, in <module>
"42" + 1
TypeError: Can't convert 'int' object to str implicitly
一般情况下,我们只需要进行强制类型转换即可:
>>> int("42") + 1
43
>>> "42" + str(1)
'421'
还有其他额外的转换方式如:
ord:将相对应的字符转换为其整型表示
chr:将整型转换为相对应的字符表示
>>> ord('s')
115
>>> chr(115)
's'
>>> S = '5'
>>> S = chr(ord(S) + 1)
>>> S
'6'
>>> int('5')
5
>>> ord('5') - ord('0')
5
我们也可以使用int来指定基数,使用bin来显示二进制数:
>>> int('1101', 2)
13
>>> bin(13)
'0b1101'
4. Changing Strings
因为字符串是不可更改的字符序列,所以我们只能新建一个字符串,然后存储所更改的字符串的结果:
>>> S = 'splot'
>>> id(S)
60510024
>>> S = S.replace('pl', 'pamal')
>>> S
'spamalot'
>>> id(S)
60483760
通过格式化字符串来新建字符串也是不错的选择:
>>> '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!'
3. String Methods
以下截图为字符串的所有方法,具体实现直接参考手册即可:
1. Changing Strings
我们可以使用replace方法来修改字符串(在JavaScript中replace可以直接带正则表达式,但是Python中不行,Python应该import re模块,然后进行字符串的操作).而我们可以给replace传递第三个参数,告诉字符串修改几个子字符串:
>>> 'aa$bb$cc$dd'.replace('$', '--')
'aa--bb--cc--dd'
>>> 'aa$bb$cc$dd'.replace('$', '--', 1)
'aa--bb$cc$dd'
>>> 'aa$bb$cc$dd'.replace('$', '--', 2)
'aa--bb--cc$dd'
备注:一般复杂的字符串操作,推荐使用正则表达式.
而如果要对字符串进行额外的一些操作,建议使用list函数将字符串转换为list,再铜鼓join将list转换为string:
>>> S = 'spammy'
>>> L = list(S)
>>> L
['s', 'p', 'a', 'm', 'm', 'y']
>>> L[3], L[4] = 'x', 'x'
>>> L
['s', 'p', 'a', 'x', 'x', 'y']
>>> S = ''.join(L)
>>> S
'spaxxy'
2. Parsing Text
我们可以通过split来分割字符串:
>>> 'aaa,bbb,ccc'.split(',')
['aaa', 'bbb', 'ccc']
3. Other Common String Methods
>>> 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
4. String Formatting Expressions
字符串格式化有两种方式:'...%s...' % (values)和'...{}...'.format(values):
>>> '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'
>>> 'That is {0} {1} bird'.format(1, "dead")
'That is 1 dead bird'
格式化的基本语法如下:
Code | Meaning |
s | 字符串 |
r | 类似s,但是以repr显示 |
c | 字符(整型或单个字符) |
d | 十进制整数 |
i | 整型 |
u | 有符号整数 |
o | 八进制 |
x | 十六进制 |
X | 十六进制,但是大写 |
e | 小写的浮点数,使用e表示 |
E | 大写的浮点数,使用e表示 |
f | 浮点数 |
F | 大写的浮点数 |
g | 浮点数:基于e或者f |
G | 浮点数:基于E或者F |
% | 等价于%% |
flags:设定一些标志,如"-"为指定宽度情况下向左靠拢,"0"则代表用0填充
>>> x = 1234
>>> res = 'integers:...%d...%-6d...%06d' % (x, x, x)
>>> res
'integers:...1234...1234 ...001234'
而%e,%f和%g用于显示不同的浮点数,我们甚至可以为它指定宽度和小数位个数:
>>> x = 1.23456789
>>> '%e | %f | %g' % (x, x, x)
'1.234568e+00 | 1.234568 | 1.23457'
>>> '%-6.2f | %05.2f | %+06.1f' % (x, x, x)
'1.23 | 01.23 | +001.2'
>>> '%s' % x, str(x)
('1.23456789', '1.23456789')
我们能可以把精度当作一个参数来进行设置:当设置为*的时候
>>> '%f, %.2f, %.*f' % (1 / 3.0, 1 / 3.0, 4, 1 / 3.0)
'0.333333, 0.33, 0.3333'
1. Dictionary-Based Formatting Expressions
我们可以通过字典的键作为索引,来达到字符串格式化的目的:
>>> '%(qty)d more %(food)s' % {'qty' : 1, 'food' : 'spam'}
'1 more spam'
实际上这也不难理解:你设定的任何变量都是以字典的方式关联起来的:
>>> food = 'spam'
>>> qty = 10
>>> vars()
{'__builtins__': <module 'builtins' (built-in)>, 'res': 'integers:...1234...1234 ...001234',
'__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__doc__': None, '__spec__': None,
'__name__': '__main__', 'qty': 10, 'food': 'spam', 'x': 1.23456789, '__package__': None}
所以,我们只要提供一个对应的字典即可:
>>> '%(qty)d more %(food)s' % vars()
'10 more spam'