根据David Beazley的page 29 of Python Essential Reference (4th Edition):
直接编写原始UTF-8编码字符串,例如
'Jalape\xc3\xb1o'
只需生成九个字符的字符串U + 004A,U + 0061,U + 006C, U + 0061,U + 0070,U + 0065,U + 00C3,U + 00B1,U + 006F,这可能不是 你的意图。这是因为在UTF-8中,多字节序列\xc3\xb1
应该代表单个字符U + 00F1,而不是 两个字符U + 00C3和U + 00B1。
这不应该是8个字符 - 不是9个字符吗?他说:\xc3\xb1
应该代表单个角色。
答案 0 :(得分:3)
不,声明是正确的。
在UTF-8 \xc3\xb1
假设代表单个字符。也就是说,如果您从UTF-8解码了字符串,那么您将得到一个字符,因此会有8个字符。
但是,在特定示例中,字符串被视为原始字符序列,而不是 UTF-8。因此,这两个八位字节会产生两个字符。
我可能会前进一点但是看到ipython的以下输出:
In [1]: b'Jalape\xc3\xb1o'
Out[1]: b'Jalape\xc3\xb1o'
In [2]: len(b'Jalape\xc3\xb1o')
Out[2]: 9
In [3]: b'Jalape\xc3\xb1o'.decode('utf8')
Out[3]: 'Jalapeño'
In [4]: len(b'Jalape\xc3\xb1o'.decode('utf8'))
Out[4]: 8
In [5]: 'Jalape\xf1o'
Out[5]: 'Jalapeño'
上面的代码适用于Python 3.对于Python 2,字节字符串(b'Jalape\xc3\xb1o'
)将替换为常规字符串('Jalape\xc3\xb1o'
),常规字符串将替换为unicode字符串({{ 1}})。
答案 1 :(得分:1)
https://groups.google.com/forum/#!topic/comp.lang.python/1boxbYjhClg
Joshua Landau(回答我的问题写道)
“直接写入原始的UTF-8编码字符串,例如'Jalape \ xc3 \ xb1o',只生成一个9个字符的字符串U + 004A,U + 0061,U + 006C,U + 0061,U + 0070,U + 0065,U + 00C3,U + 00B1,U + 006F,这可能不是你想要的。这是因为在UTF-8中,多字节序列\ xc3 \ xb1应该代表单个字符U + 00F1 ,而不是两个字符U + 00C3和U + 00B1。“
正确。
我原来的问题是:这不应该是8个字符 - 不是9个字符吗?
不,Python往往对这些事情是正确的。
他说:\ xc3 \ xb1应该代表单个字符。然而,在与Pythonistas的一些互动之后,我更加困惑。
按照他说的方式,你会的。
参考上述段落: 1.“写一个原始的UTF-8编码字符串”是什么意思???
嗯,这并不像他给出的那样没有上下文。
在Python2中,曾经可以做'Jalape funny-n o'。这是一个'字节'字符串,其中每个字形在内部存储时长度为1个字节,因此每个字形根据字符集ASCII或Latin-1与整数相关联。如果这些字符集有一个搞笑的字形然后yay!别的,不!这里没有UTF-8 !!或UTF-16 !!这些是普通字节(8位)。
Unicode是字形和整数之间非常大的映射表,表示为Uxxxx或Uxxxx-xxxx。
等待我们的常驻unicode专家解释你实际上是错的原因
UTF-8 UTF-16是以高效方式存储这些大整数的编码。所以当DB说“编写一个原始的UTF-8编码字符串”时 - 这样做的唯一方法是使用Python3,其中默认的字符串文字存储在Unicode中,然后在内部使用UTF-8 UTF-16来存储各自结构中的字节数;或者,可以使用u'Jalape',这两种语言都是unicode(注意领先的'u')。
正确。
- 所以假设这是Python 3:'Jalape \ xYY \ xZZ o'(可读性的空间)DB所说的是,愚蠢的用户会期望Jalapeno有一个波浪形的n但是他得到的是:Jalape funny1 funny2 o(可读性空间)-9个字形或9个Unicode点或9个UTF8字符。正确的吗?
醇>
我想是的。
- 这让我想知道他的意思是: “这是因为在UTF-8中,多字节序列\ xc3 \ xb1应该代表单个字符U + 00F1,而不是两个字符U + 00C3和U + 00B1”
醇>
他把一些事情搞混了,AFAICT。
有人可以花时间仔细阅读并澄清数据库的含义吗?
以下是一个简单的解释:你错了(或者你们两个几乎正确):
从Python 3开始:
>>> "\xc3\xb1"
'ñ'
>>> b"\xc3\xb1".decode()
'ñ'
“什么?”你尖叫,“那是错的!”但事实并非如此。让我解释一下。
Python 3的字符串要求你分别给每个字符( * winces
如果我错了* )。 Python将"\xc3"
解释为"\N{LATIN
CAPITAL LETTER A WITH TILDE}"
,将"\xb1"
解释为"\N{PLUS-MINUS SIGN}"
¹。
这意味着Python被赋予两个字符。 Python基本上就是
这样做:
number = int("c3", 16) # Convert from base16
chr(number) # Turn to the character from the Unicode mapping
当您提供Python 原始字节时,您说的就是这个 字符串在编码时看起来像 - 你没有给出Python Unicode, 但编码的Unicode 。这意味着当你解码它时(.decode()) 可以将多字节部分转换为相关字符。
要查看编码字符串与字符串本身的不同,请参阅:
>>> "Jalepeño".encode("ASCII", errors="xmlcharrefreplace")
b'Jalepeño'
那些代表同样的东西,但第一个(根据Python) 是的东西,第二个需要解码。
现在,将其恢复原状:
>>> "\xc3\xb1".encode()
b'\xc3\x83\xc2\xb1'
您可以看到编码的字节代表两个字符; 您在上面看到的字符串是而不是编码的字符串。编码是 Python内部。
我希望有所帮助;祝你好运。
¹请注意,我发现"\N{...}"
表格更容易阅读,并推荐它。