7

显然,我可以在 Python 2.7 中做到这一点:

value = '國華'

似乎 Python 正在使用一种编码将字符串文字中的字符编码为字节字符串。那是什么编码?是 中定义sys.getdefaultencoding()的编码,源文件的编码,还是别的什么?

谢谢

4

2 回答 2

7

getdefaultencoding与源文件或终端的编码无关。它是用于将字节字符串隐式转换为 Unicode 字符串的编码,在 Python 2.X 上应始终为“ascii”(在 Python 3.X 上为“utf8”)。

在 Python 2.X 上,脚本中未声明编码的代码行会产生错误:

SyntaxError: Non-ASCII character '\x87' in file ...

实际的非 ASCII 字符可能会有所不同,但如果没有编码声明,它将无法工作。在 Python 2.X 上使用非 ASCII 字符需要编码声明。编码声明必须与源文件编码匹配。例如:

# coding: utf8
value = '國華'

当保存为 cp936 时产生:

SyntaxError: 'utf8' codec can't decode byte 0x87 in position 9: invalid start byte

当编码正确时,字节字符串中的字节就是源文件中的字节,因此它将包含字符的编码字节。当 Python 解析 Unicode 字符串时,使用声明的源编码将字节解码为 Unicode。请注意在 cp936 控制台上打印 UTF-8 字节字符串和 Unicode 字符串时的区别:

# coding: utf8
value = '國華'
print value,repr(value)
value = u'國華'
print value,repr(value)

输出:

鍦嬭彲 '\xe5\x9c\x8b\xe8\x8f\xaf'
國華 u'\u570b\u83ef'

字节字符串包含两个字符的 3 字节 UTF-8 编码,但由于 cp936 终端不理解字节序列,因此显示不正确。Unicode 打印正确,字符串包含从源文件的 UTF-8 字节解码的 Unicode 代码点。

注意声明和使用与终端匹配的编码时的区别:

# coding: cp936
value = '國華'
print value,repr(value)
value = u'國華'
print value,repr(value)

输出:

國華 '\x87\xf8\xc8A'
國華 u'\u570b\u83ef'

字节字符串的内容现在是两个字符的 2 字节 cp936 编码('A' 等同于 '\x41')并且由于终端理解 cp936 字节序列而正确显示。Unicode 字符串包含与前一个示例相同的两个字符的 Unicode 代码点,因为源字节序列是使用声明的 Unicode 源编码解码的。

如果脚本具有正确的源编码声明并使用 Unicode 字符串作为文本,它将显示正确的字符1而不管终端编码2UnicodeEncodeError如果终端不支持该字符而不是显示错误的字符,它将抛出一个。

最后一点:除非另有声明,否则 Python 2.X 默认为 'ascii' 编码,并且如果编码支持非 ASCII 字符,则允许在字节字符串中使用它们。Python 3.X 默认为 'utf8' 编码(因此请确保保存在该编码中或以其他方式声明),并且不允许在字节字符串中使用非 ASCII 字符。

1如果终端字体支持该字符。
2如果终端编码支持该字符。

于 2012-08-17T04:16:32.773 回答
0
value = b'國華'

是没有意义的(b在 Python 2.x 中隐含) - 为什么你想要一个包含字符的字节字符串?Python 只是以您的终端/编辑器使用的任何编码来复制字节。你想要的是一个字符串

value = u'國華'

在源代码文件(与交互式 shell 相对)中,不要忘记通过在文件开头添加以下行来声明编码:

# -*- coding: utf-8 -*-
于 2012-08-16T18:35:01.610 回答