本章范围
本章主要讲str
字符串类型,有关的操作适用于Unicode处理。
Unicode简介
ASCII是Unicode的简单形式,但Unicode适用于非英语地区的人们。两者在文件中的编码不同。
-
在Python 3.X中,有三种字符串类型:
str
用于Unicode文本,bytes
用于二进制数据,bytearray
是bytes
的一种可修改的变体。 -
在Python 2.X中,
unicode
字符串表示Unicode文本,str
同时处理8位文本和二进制数据。
实际上,Unicode的主要不同在于它在内存和文件之间来回移动所要求的转换步骤。除此之外它大体上只是一个字符串处理过程。
字符串基础
字符串可以用来表示能够编码为文本或字节的人和事物。Python的字符串有一套强大的处理工具集,并划分为不可变序列的类型(即不能在原位置修改字符串)。
以下是常见的字符串字面量和操作:
操作 | 解释 |
---|---|
S = '' |
空字符串 |
S = "spam's" |
双引号,和单引号相同 |
S = 's\np\ta\x00m |
包含转义序列 |
S = """...multiline...""" |
三引号块字符串 |
S = r'\temp\spam' |
原始字符串,不转义 |
B = b'sp\xc4m' |
字节串 |
U = u'sp\u00c4m' |
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.endwith('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) |
返回单个字符的ASCII序号 |
`re.match('sp(.*)am', line) | 模式匹配:库模块 |
除了上述工具集,Python还有支持更高级的字符串方法,如正则表达式匹配、XML解析器等的。
字符串字面量
Python的字符串有许多方法编写:
-
单引号:
'spa"m'
-
双引号:
"spa'm"
-
三引号:
'''...spam...''', """...spam..."""
-
转义序列:
"s\tp\na\0m"
-
原始字符串:
r"C:\new\test.spm"
-
字节字面量:
b'sp\x01am'
-
Unicode字面量:
u'eggs\u0020spam'
单引号和双引号字符串是一样的
Python支持单引号和双引号的原因是,解决字符串中含有"
或'
的问题。但是,如果字符串中没有单引号,最好使用单引号字符串(Python显示字符串时也是单引号)。
>>> "123"
'123'
如果我们忘记了用逗号把字符串分开,那么Python会自动拼接相邻的字符串字面量:
>>> 'Meaning ', 'of ', 'life'
('Meaning ', 'of ', 'life')
>>> "Meaning " 'of ' "life"
'Meaning of life'
如果字符串中既有单引号又有双引号,我们可以使用转义字符:
>>> 'knight\'s'
"knight's"
>>> "knight\"s"
'knight"s'
转义序列代表特殊字符
反斜杠用来引入特殊的字符编码,称为转义序列。它帮助我们在字符串中嵌入不容易通过键盘输入的字符。看上去,以\
为开头的转义字符占两个字节,但其实只占一个。
直接在交互界面上输入字符串变量,不会解释转义字符,print
解释转义字符。
>>> s = 'a\nb\tc'
>>> s
'a\nb\tc'
>>> print(s)
a
b c
上面的字符串包含5个字符,分别是:a
、换行、b
、制表、c
。但不是5字节(因为字符串以Unicode编码)。反斜杠没有存进去。
Python的转义字符序列如下表:
转义 | 意义 |
---|---|
\newline |
被省略(行的延续) |
\\ |
范斜杠(保留一个\ ) |
\' |
单引号 |
\" |
双引号 |
\a |
响铃 |
\b |
退格 |
\f |
换页 |
\n |
换行 |
\r |
回车 |
\t |
水平制表符 |
\v |
垂直制表符 |
\xhh |
十六进制值hh 的字符 |
\ooo |
八进制值为ooo 的字符 |
\0 |
空字符 |
\N{ id } |
Unicode数据库ID |
\uhhhh |
16位十六进制的Unicode字符 |
\Uhhhhhhhh |
32位十六进制的Unicode字符 |
\other |
不转义,保留\ 和\other |
嵌入绝对二进制数值的操作,注意到,Python在计算字符串长度时不会以到达空字符为标准,任何字符都不会结束Python的字符串。
>>> s = 'a\0b\0c'
>>> s
'a\x00b\x00c'
>>> len(s)
5
不管如何指定不可打印字符(如空字符),Python的print
都会把它们打印出来。
>>> S = "s\tp\na\x00m"
>>> S
's\tp\na\x00m'
>>> print(S)
s p
am
如果Python认为\
后面的字符不是有效的转义编码,那么它会生成字符串中的保留反斜杠:
>>> x = "C:\py\code"
>>> x
'C:\\py\\code'
>>> len(x)
10
最好的办法是,如果要讲斜杠写进字符串中,则写反斜杠。
原始字符阻止转义
我们想打开一个绝对路径下的文件:
>>> myfile = open('C:\new\text.dat', 'w')
此时,Python将其解释为:'C:'
,换行,'ew'
,制表符,'ext.dat'
。要解决这个问题(保留反斜杠),可以用双反斜杠,或者在前字符串面加一个r
。
>>> r'C:\new\text.dat'
'C:\\new\\text.dat'
三引号编写多行块字符串
三引号可以便捷地编写多行的文本。
>>> 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.
注意到,对这种连续的行而言,交互提示符会变成...
(在编写函数、循环时也会遇到这种情形)。
实际上,三引号字符串会保留所有范围的文本,包括注释。
>>> menu = """spam # comments here added to string!
... eggs
... """
>>> menu
'spam\t\t# comments here added to string!\neggs\n'
三引号的文本块也可以被当成注释,我们可以用三引号注释掉多行代码(此时Python运行时跳过这些被三引号注释掉的代码)。
实际应用中的字符串
基本操作
字符串的长度、用+
拼接、用*
重复:
>>> len('abc')
3
>>> 'abc' + 'def'
'abcdef'
>>> 'Ni!' * 4
'Ni!Ni!Ni!Ni!'
可以用for
循环对字符串的每个字符迭代,其中的in
表示字符c
用于指代字符串中的各个元素;可以用in
方法检测字符串是否为字串(返回布尔值,而str.find()
返回数字):
>>> 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
索引和分片
Python的偏移量从0开始,以比字符串长度小于1的偏移量结束,且支持负偏移量。分片[i:j]
表示从偏移i
到偏移j-1
的子串,其中如果i
省略了,那么默认为0;如果j
省略了,那么默认为字符串的长度。
>>> S = 'spam'
>>> S[1], S[0], S[-2]
('p', 's', 'a')
>>> S[1:3], S[1:], S[:-1]
('pa', 'pam', 'spa')
索引的图示:
细节:
- 索引
S[i]
:第一个元素偏移量为0,S[-i]
表示倒数第i
个字符; - 分片
S[i:j]
提取序列的连续部分:包含下边界i
,不包含上边界j
,i
、j
缺省时默认为0和字符串的长度; - 扩展分片
S[i:j:k]
:接受一个步长为k
的字符串,默认值为1。
扩展分片:第三个限制值和分片对象
X[i:j:k]
表示:提取X
中的全部元素,从偏移量i
到j-1
,每隔k
个元素索引一次,k
默认为+1。
比如,X[1:10:2]
会取出X
中偏移量为1-9之间,每隔一个元素的元素,它收集X[1], X[3], X[5], X[7], X[9]
。
>>> S = 'abcdefghijklmnop'
>>> S[1:10:2]
'bdfhj'
当k
为-1,我们可以反转字符串,实际上,当k
为复数,从右(j-1
)到左(i
)提取:
>>> S = 'hello'
>>> S[::-1]
'olleh'
分片的另外一种形式:使用slice
函数转换元组。
>>> 'spam'[slice(1, 3)]
'pa'
>>> 'spam'[slice(None, None, -1)]
'maps'
字符串转换工具
字符串不能和数字相加。但是,我们让数字和字符串相互转换:
>>> int("42"), str(42)
(42, '42')
>>> repr(42)
'42'
int
将字符串转换为数字,str
将数字转换为字符串。repr
函数有些特殊,它将一个对象作为参数,返回可作为代码的字符串对象,也就是说,可以运行该字符串重建被转换的对象。
>>> str('spam')
'spam'
>>> repr('spam')
"'spam'"
因此,我们可以手动转换类型:
>>> S = '42'
>>> I = 1
>>> S + I
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str
>>> int(S) + I
43
>>> S + str(I)
'421'
字符串代码转换
ord
将单个字符转换为ASCII码,chr
则相反。
>>> ord('s')
115
>>> chr(115)
's'
字符转换为数字后,可以进行运算。这样,我们就可以手动地实现字符串转换为整数的过程(循环会在后面介绍)。
>>> S = '114514'
>>> I = 0
>>> while S != '':
... I = I * 10 + (ord(S[0]) - ord('0'))
... S = S[1:]
...
>>> I
114514
修改字符串 I
不能在原位置修改字符串。
>>> S = 'spam'
>>> S[0] = 'x'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
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!'
可以看作是,把对象转换为字符串,再根据指定的方式改变最初的字符串。
字符串方法
方法调用语法
方法是与特定对象相关联,并作用于特定对象的简单函数。它们是附属于对象的属性,引用的是可调用函数。调用方法时,结合两次操作:一次属性获取和一次函数调用。
-
属性获取:
object.attribute
-
调用表达式:
function(arguments)
合并两者可以调用一个对象方法。方法调用表达式为object.method(arguments)
。Python首先获取对象object
的方法attrinute
,然后调用它,传递进对象object
和参数arguments
。即使用参数调用方法来处理对象。
字符串的方法
以下是Python 3.3的字符串方法,其中[]
表示方括号里面的内容可以填,也可以省略:
S.capitalize() S.ljust(width [, fill])
S.casefold() S.lower()
S.center(width [, fill]) S.lstrip([chars])
S.count(sub [, start [, end]]) S.maketrans(x[, y[, z]])
S.encode([encoding [,errors]]) S.partition(sep)
S.endswith(suffix [, start [, end]]) S.replace(old, new [, count])
S.expandtabs([tabsize]) S.rfind(sub [,start [,end]])
S.find(sub [, start [, end]]) S.rindex(sub [, start [, end]])
S.format(fmtstr, *args, **kwargs) S.rjust(width [, fill])
S.index(sub [, start [, end]]) S.rpartition(sep)
S.isalnum() S.rsplit([sep[, maxsplit]])
S.isalpha() S.rstrip([chars])
S.isdecimal() S.split([sep [,maxsplit]])
S.isdigit() S.splitlines([keepends])
S.isidentifier() S.startswith(prefix [, start [, end]])
S.islower() S.strip([chars])
S.isnumeric() S.swapcase()
S.isprintable() S.title()
S.isspace() S.translate(map)
S.istitle() S.upper()
S.isupper() S.zfill(width)
S.join(iterable)
字符串方法示例:修改字符串II
上面我们讲过,我们可以用分片和拼接的组合,或者是replace
方法来替换子字符串。事实上,replace
可以替换字符串中的所有匹配的字串:
>>> 'aa$bb$cc$dd'.replace('$', 'SPAM')
'aaSPAMbbSPAMccSPAMdd'
因此,replace
可以实现模板替换。
如果要替换任意偏移量处出现的字串,可以再做一次替换(使用find
搜索字串、分片拼接):
>>> S = 'xxxxSPAMxxxxSPAMxxxx'
>>> where = S.find('SPAM')
>>> where
4
>>> S = S[:where] + 'EGGS' + S[(where+4):]
>>> S
'xxxxEGGSxxxxSPAMxxxx'
find
函数找出字符串中第一个匹配字串的偏移量,没找到时返回-1。
但是,这种方法每次操作都需要创建一个新的字符串对象,时间代价跟打。因此我们可以将字符串转换为可修改的对象(list
将任意序列转换为列表,元素的顺序不变):
>>> S = 'spammy'
>>> L = list(S)
>>> L
['s', 'p', 'a', 'm', 'm', 'y']
再在列表中修改字符:
>>> L[3] = 'x'
>>> L[4] = 'x'
>>> L
['s', 'p', 'a', 'x', 'x', 'y']
然后,在将其转换回一个字符串。join
方法将列表中的字符/字符串从左到右拼接为一个字符串:
>>> S = ''.join(L)
>>> S
'spaxxy'
join
方法:
>>> 'SPAM'.join(['eggs', 'sausage', 'ham', 'toast'])
'eggsSPAMsausageSPAMhamSPAMtoast'
字符串方法示例:解析文本
如果某些分隔符分开了数据组件,我们可以通过分割split
拿出这些组件。
>>> line = 'aaa bbb ccc'
>>> cols = line.split()
>>> cols
['aaa', 'bbb', 'ccc']
split
方法将一个字符串从分隔符处切成一系列字串。默认的分隔符为空白。也可以根据实际情分割字符串:
>>> line = 'bob,hacker,40'
>>> line.split(',')
['bob', 'hacker', '40']
实际应用中的其他常见字符串方法
清除空白(以strip结尾):
>>> line = " a b c "
>>> line.strip()
'a b c'
>>> line.rstrip()
' a b c'
大小写转换:
>>> line.upper()
'AJAKSOSKASA'
>>> line.lower()
'ajaksoskasa'
>>> line.title()
'Ajaksoskasa'
是否复合某一特征(以is
开头):
>>> line = "abs"
>>> line.isalpha()
True
是否以特定字符串为开头/结尾:
>>> line = "The knights who say Ni!\n"
>>> line.endswith('Ni!\n')
True
>>> line.startswith('The')
True
替代的技巧可以取得与字符串方法相同的效果。如:S[-len(sub):] == sub
相当于S.endswith(sub)
。
原始string模块的函数(在Python 3.X中被删除)
在Python出现的最初10年,Python只提供string
模块,这在之后成为了遗留问题。由于这部分涉及的方面过于古老,故不做相关笔记。
字符串格式化表达式
字符串格式化允许在单个步骤中对一个字符串执行多个特定类型的替换。如今,Python中的字符串格式化可以用两种方式实现:
- 字符串格式化表达式:
'...%s...' % (values)'
- 字符串格式化方法调用:
'...{}...'.format(values)'
这一节主要讲第一种方式。
格式化表达式基础
应用在字符串时,%
运算符提供了根据格式定义,将不同类型的值格式化为字符串的简单方法。
格式化字符串:
-
在
%
运算符左侧放置一个需要进行格式化的字符串,这个字符串带有一个或多个内嵌的转换目标,以%
开头(如%d
)。 -
在
%
运算符右侧放置一个(或多个内嵌在元组中的)对象,这些对象会插入到左侧的字符串中,替换其中的转换目标。
比如,在这个例子中,整数1
替换格式化字符串左边的%d
,字符串'dead'
替换%s
,得到一个新的字符串。
>>> 'That is %d %s bird!' % (1, 'dead')
'That is 1 dead bird!'
需要注意,所有的类型适用于%s
的替换(但主要用于字符串),且当一个值插入时,直接在%
右侧写下这个值;多个值插入时,需要元组。
>>> exclamation = 'Ni'
>>> 'The knights who say %s!' % exclamation
'The knights who say Ni!'
>>> '%d %s %g you' % (1, 'spam', 4.0)
'1 spam 4 you'
>>> '%s -- %s -- %s' % (42, 3.14159, [1, 2, 3])
'42 -- 3.14159 -- [1, 2, 3]'
高级格式化表达式语法
我们可以在格式化表达式中使用下表列出的任何一种转换类型的代码,它们出现在转换目标中的%
的后面,学过C语言的会非常熟悉。
代码 | 意义 |
---|---|
s |
字符串、任何对象的str(X) 字符串 |
r |
字符串、任何对象的repr(X) 字符串 |
c |
字符(int 或str ) |
d |
十进制 |
i |
整数 |
u |
同d |
o |
八进制整数 |
x |
十六进制整数 |
X |
同x |
e |
带有指数的浮点数(科学计数法) |
E |
同e |
f |
十进制浮点数 |
F |
同f |
g |
浮点数e 或f |
G |
浮点数E 或F |
% |
% 字面量 |
转换目标的一般结构是这样的(方括号表示可以省略):
%[(keyname)][flags][width][.precision]typecode
其中,keyname
为表示索引在表达式右侧使用的字典提供键名称;flags
说明格式的标签,有左对齐-
、数值符号+
、正数前的空白以及负数前的符号(右对齐)
、零填充0
;width
为被替换的文本给出总的最小字段宽度,.precision
为浮点数设置小数点后面的数位。
width
和precision
可以设置为*
,表示它们应该从表达式右侧的输入值的下一项取值(而这个项用于替换*
)。
高级格式化表达式举例
这个例子显示了flags
的作用:
>>> x = 1234
>>> res = 'integers: ...%d...%-6d...%06d...% 6d' % (x, x, x, x)
>>> res
'integers: ...1234...1234 ...001234... 1234'
显示浮点数的三种方式,其中%e
显示指数(科学计数法),%g
根据数字内容选择格式,如果指数小于-4或者不小于精度,那么用%e
,否则用%f
。
>>> x = 1.23456789
>>> '%e | %f | %g' % (x, x, x)
'1.234568e+00 | 1.234568 | 1.23457'
使用*
在表达式右侧中得到宽度与精度:
>>> '%f, %.2f, %.*f' % (1/3.0, 1/3.0, 4, 1/3.0)
'0.333333, 0.33, 0.3333'
基于字典的格式化表达式
字符串格式化允许左边的目标引用右边编写的字典中的键来提取对应的值:
>>> '%(qty)d more %(food)s' % {'qty': 1, 'food': 'spam'}
'1 more spam'
左边通过格式化字符串中的(qty)
和(food)
分别引用右边字典的键'qty'
和'food'
,提取对应的值。
我们可以建立一个字典,并利用单个基于键的引用的格式化表达式一次性替换它们。这种小技巧一般配合var()
使用,var()
返回的字典包含了所有存在的变量:
>>> vars()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'exclamation': 'Ni', 'x': 1.23456789, 'res': 'integers: ...1234...1234 ...001234... 1234'}
字符串格式化方法调用
字符串格式化方法基础
在Python 2.6之后的版本中,可以使用字符串的format
方法,它是函数调用而不是表达式。
在主体字符串中,花括号通过位置、关键字或相对位置指定替换目标和将要插入的参数。
通过位置替换:
>>> 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 = '{}, {} and {}'
>>> template.format('spam', 'ham', 'eggs')
'spam, ham and eggs'
看上去,上一节的字符串格式化表达式更简洁。本质上,格式化方法中字符串的{}
相当于上一节的%s
,任何类型可以在目标上替换。
>>> '{motto}, {0} and {food}'.format(42, motto=3.14, food=[2,1])
'3.14, 42 and [2, 1]'
format
方法也是创建一个新的字符串。
添加键、属性和偏移量
格式化方法调用也是可以扩展。例:
>>> import sys
>>> 'My {1[kind]} runs {0.platform}'.format(sys, {'kind': 'laptop'})
'My laptop runs win32'
>>> 'My {map[kind]} runs {Sys.platform}'.format(Sys=sys, map={'kind': 'laptop'})
'My laptop runs win32'
点表示通过位置或关键字引用的元素的对象属性,格式化字符串中的方括号可以指定字典的键,也可以指定列表的偏移量来执行索引。
>>> somelist = list('SPAM')
>>> 'first={0[0]}, third={0[2]}'.format(somelist)
'first=S, third=A'
高级格式化方法语法
如下,是可以在一个格式化字符串中作为可替代目标出现的形式化结构:
{fieldname component !conversionfig :formatspec}
其中,
-
fieldname
是辨识参数的一个可选的数字或关键字; -
component
是有着若干个/零个".name"
或[index]
引用的字符串,其中.name
获取参数的方法,[index]
获取参数的属性/索引值; -
conversionfig
如果出现,前面会带!
,后面跟着r
,s
或a
,分别调用repr
、str
和ascii
函数; -
formatspec
如果出现,则以:
开始,后面跟着一些文本。
formatspec
的格式如下:(这里中括号表示可以不填)
[[fill]align][sign][#][0][width][,][.precision][typecode]
其中,
fill
可以是任意的填充字符(除了{
和}
);align
可以是<
、>
、=
或^
,分别表示左对齐、右对齐、前面的符号字符填充、居中;sign
可以是+
、-
或空格,用于显示数值类型的符号;width
和precision
与字符串格式化表达式相同;typecode
可以参照介绍字符串格式化表达式时给出的表,也可以是b
,用于表示二进制。
高级格式化方法举例
{0:10}
表示第一个参数至少占一个10字符宽的字段,{1:<10}
表示在一个10字符宽的字段中左对齐,{0.platform:>10}
意味着第一个参数的platform
属性在10字符宽的字段中右对齐。这里使用了dict
方法创建字典:
>>> import sys
>>> '{0:10} = {1:10}'.format('spam', 123.4567)
'spam = 123.4567'
>>> '{0:>10} = {1:<10}'.format('spam', 123.4567)
' spam = 123.4567 '
>>> '{0.platform:>10} = {1[kind]:<10}'.format(sys, dict(kind='laptop'))
' win32 = laptop '
我们可以省略:
前面的0
和1
,这样会使可读性降低。
浮点数支持与%
表达式中相同的类型代码和格式化声明。
>>> '{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:.{1}f}'.format(1 / 3.0, 4)
'0.3333'
我们也可以用format
函数格式化单独的一项:
>>> format(1.2345, '.2f')
'1.23'
与%格式化表达式比较
在执行相同的功能时,%
格式化表达式总是更容易编写。但是,format
表达式拥有%
表达式没有的高级功能。
为什么使用格式化方法
格式化方法的特性:
- 拥有
%
表达式自身没有的少量额外功能 - 拥有更为灵活的值引用语法
- 能够使替换值的引用更加清楚明确
- 牺牲一个运算符以换取更容易记忆的方法名称
- 对于单个或多个值并不允许不同的语法
- 作为一个函数可以在表达式不能使用的地方使用
额外特性:特殊情况的“电池”vs通用技术
支持二进制格式化、自由选择千分位是否用逗号隔离。
灵活的引用语法:额外地复杂性和功能的重叠
显式的值引用:如今变得可选和不常用
如果右多个值需要替换到格式字符串中,那么用%
会更加简洁,但是format
更加易读。但是这些值替换到格式字符串中有额外要求,那么可能%
的简洁性会消失。
命名的方法与上下文中立的参数:美学vs应用
对于初学者而言,format
方法更容易理解,但是语法也更为严格。
功能vs表达式:微小的便利
通用类型分类
对于内置类型,对处于同一分类的类型的操作,运行起来都是一样的。
同一分类中的类型共享同一个操作集
我们可以在将要学习的全部序列类型上,执行本章中在字符串上使用的相同序列操作,包括拼接、索引、迭代。Python有三大类型,以及对应的一般特性:
- 数字:支持加法、乘法等;
- 序列:支持索引、分片、拼接等;
- 映射:支持按键名的索引。
可变类型能够在原位置修改
根据能否在原位置修改对象的区分,我们可以划分为两个分类:
- 不可变类别:数字、字符串、元组、不可变集合
- 可变类别:列表、字典、集合、字节数组