字符串字面量——转义序列代表特殊字符

未匹配的标注

最后一个例子通过在引号前放置一个反斜杠,在字符串中嵌入引号。这代表了字符串中的一个通用模式:反斜杠用来引入被称为转义序列的特殊字符编码。

转义序列让我们可以在字符串中嵌入那些不能被轻易键入的字符。字符\,和它后面的一个或多个字符串字面量,被结果字符串对象(它拥有被转义系列指定的二进制值)中的一个字符代替。比如,下面是一个五字符的字符串,嵌入了一个换行符和一个制表符:

>>> s = 'a\nb\tc'

两个字符\n代表了一个单字符——字符集中的换行字符的二进制值(在ASCII中,字符码 10)。类似地,序列\t被tab字符所代替。这个字符串打印时看起来的样子取决于如何打印。交互式回显将特殊字符显示为转义,但print却解释它们:

>>> s
'a\nb\tc'
>>> print(s)
a
b c

要完全确定在字符串中真的有多少字符,使用内置len函数——它返回了字符串中确切的字符数,而不管它是如何编码或显示的:

>>> len(s)
5

这个字符串有5个字符长:它包含了一个 ASCII a,一个换行符,一个ASCII b等等。

注意:

如果习惯了所有都是ASCII编码的文本,还很容易将这个结果想为5个字节,但很可能不应该这么想。真的,“字节”在Unicode世界没有意义。首先,在Python中字符串对象在内存中很可能更大(译注:也就是说,单凭字节数无法判定内存大小)。

更重要的是,在Unicode世界字符串内容和长度都反映了码点(识别号),在那里单字符不一定直接映射为单字节(不管是在文件中编码时或在内存中存储时)。这种映射可能对简单的7比特 ASCII 文本适用,但即使是这种适用也取决于外部的编码类型和使用的内部存储方案。比如,在UTF-16下,ASCII字符在文件中时多个字节,且它们在内存中可能是1,2,4字节,这取决于Python是如何分配它们的空间的。对于其它字符(非ASCII文本),它们字符的值可能太大了以至于在8比特字节中无法容纳下,字符到字节的映射完全无法适用。

事实上,3系列将str字符串正式定义为Unicode码点序列而非字节来明确这一点。如果想知道的话,在第37章中有更多关于字符串内部是如何存储的知识。就现在而言,为了安全起见,请认为字符串中是字符而非字节。在这一点上请相信我;作为一个有经验的C程序员,我也需要打破旧有习惯!

注意在前面结果中的原来的反斜杠字符在内存中并不是真的和字符串存储在一起;它们只是被用来描述存储在字符串中的特殊字符。为了编码这些特殊字符,Python识别一整套转义码序列,列在表7-2中。
image-20230226193205417

image-20230226193234084

一些转义序列允许将绝对的二进制值嵌入到字符串的字符中。比如,下面是一个5个字符的字符串,它嵌入了两个二进制0值的字符(编码为一位的八进制转义):

>>> s = 'a\0b\0c'
>>> s
'a\x00b\x00c'
>>> len(s)
5

在 Python中,像这样的0(null)字符并不会像在C语言中的“空字节”通常那样终止一个字符串。相反,Python将这个字符串的长度和文本都保留在内存中。事实上,在Python中没有字符可以终止一个字符串。下面是一个全是绝对二进制转义码组成的字符串——二进制1和2(以8进制编码),跟着一个二进制3(以16进制编码):

>>> s = '\001\002\x03'
>>> s
'\x01\x02\x03'
>>> len(s)
3

注意Python以16进制显示不可打印的字符,而不管它们是以何种进制指定的。可以自由地组合绝对值转义和表7-2中的更符号化的转义类型。下面字符串包含了字符串“spam”,一个tab和换行,还有一个以16进制编码的绝对0值字符串:

>>> S = "s\tp\na\x00m"
>>> S
's\tp\na\x00m'
>>> len(S)
7
>>> print(S)
s p
a m

当在Python中处理二进制数据文件时,这变得更加重要。因为在脚本中它们的内容是表示为字符串的,所以处理包含任何种类的二进制字节值的二进制文件是没问题的——当以二进制模式打开时,文件从外部文件发回原始字节的字符串(在第4,9,37章中有更多关于文件的知识)。

最后,如表7-2的最后一条所暗示的,如果Python不能识别\后的字符为有效转移码,则会在结果字符串中简单地保留\

>>> x = "C:\py\code" # 原封不动保留 \  (并将其显示为 \\)
>>> x
'C:\\py\\code'
>>> len(x)
10

然而,除非确保能记住表7-2的所有内容(而且你的头脑很可能有比记忆这个表更好的用处!),不应该依赖这个行为。要明确地编码字面上的反斜杠,让它们保留在字符串中,使用双反斜杠(\\是对\的转义)或使用原始字符串(下一节展示了如何做)。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 查看所有版本


暂无话题~