用于 u"" 字面量的编码

6
考虑下面的例子:
>>> s = u"баба"
>>> s
u'\xe1\xe0\xe1\xe0'
>>> print s
áàáà

我正在idle中使用cp1251编码,但似乎解释器实际上使用latin1来创建Unicode字符串:
>>> print s.encode('latin1')
баба

为什么会这样?是否有规范来控制这种行为?
CPython,2.7版。
编辑 我实际要找的代码是:
>>> u'\xe1\xe0\xe1\xe0' == u'\u00e1\u00e0\u00e1\u00e0'
True

似乎当使用 latin1 编解码 Unicode 时,小于256的所有Unicode点都被保留不变,因此结果是我之前输入的字节。


3
你提出的问题有误。正确的问题不是“Unicode字符串字面值使用了哪种编码”(这是一个毫无意义的问题;编码是输入/输出的事情,内部表示显然必须能够表示Unicode,这就是你需要知道的全部)。你真正想知道答案的问题是“为什么IDLE破坏了我的文本编码,它是在输入还是输出时发生的,以及我该如何让它按照我的意愿工作?” - kindall
3
你是如何定义编码的?请参考http://www.python.org/dev/peps/pep-0263/来定义源文件中的编码方式。同时请提供你所使用的Python版本。根据http://docs.python.org/howto/unicode.html,如果没有指定编码方式,Python默认使用ASCII编码。在Python 2.4之前的版本中,以欧洲为中心并默认使用Latin-1作为字符串的编码方式。 - Gagandeep Singh
@kindall 嗯,据我所知,在创建Unicode对象时我们确实需要进行编码(因为我们需要的不是字节,而是有意义的字符)。那么为什么解释器不使用我的实际编码来执行字节->字符转换呢? - Roman Bodnarchuk
@Gagandeep,cp1251只是我的操作系统默认编码。 - Roman Bodnarchuk
1
解释器无法知道编码,除非您提供它。 - Karoly Horvath
1个回答

8
当你在终端中输入字符,例如б,你会看到一个б,但实际上输入的是一系列字节序列。
由于你的终端编码是cp1251,因此输入баба会生成与在cp1251编码下编码为баба的unicode相等的字节序列。
In [219]: "баба".decode('utf-8').encode('cp1251')
Out[219]: '\xe1\xe0\xe1\xe0'

(请注意,我在上面使用了 utf-8 ,因为我的终端编码方式是 utf-8 ,而不是 cp1251 。对我来说,“баба”。 decode('utf-8')只是 баба 的unicode代码。)
由于输入баба会产生字节序列\xe1\xe0\xe1\xe0,所以当您在终端中输入 u“баба”时,Python 实际收到的是u'\xe1\xe0\xe1\xe0'。这就是为什么你能看到的。
>>> s
u'\xe1\xe0\xe1\xe0'

这个Unicode恰好代表áàáà

当您输入时,

>>> print s.encode('latin1')

latin1编码将u'\xe1\xe0\xe1\xe0'转换为'\xe1\xe0\xe1\xe0'

终端接收到字节序列'\xe1\xe0\xe1\xe0',并使用cp1251对其进行解码,从而打印出баба

In [222]: print('\xe1\xe0\xe1\xe0'.decode('cp1251'))
баба

尝试:

>>> s = "баба"

改用不带u的方法。

>>> s = "баба".decode('cp1251')

使s成为unicode。或者,使用冗长但非常明确(并且终端编码不可知)的方式:

>>> s = u'\N{CYRILLIC SMALL LETTER BE}\N{CYRILLIC SMALL LETTER A}\N{CYRILLIC SMALL LETTER BE}\N{CYRILLIC SMALL LETTER A}'

或者使用较短但难以理解的方式表达。
>>> s = u'\u0431\u0430\u0431\u0430'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接