<h3>对问题1的回答:</h3>
<p>在Python版本<;3.3中,Unicode字符串<code>u''</code>的长度是使用的UTF-16或UTF-32代码单元数(取决于生成标志),而不是字节数。<code>\u4e25</code>是一个代码单元,但如果使用UTF-16(Windows上的默认值),则并非所有字符都由一个代码单元表示。</p>
<pre><code>>>> len(u'\u42e5')
1
>>> len(u'\U00010123')
2
</code></pre>
<p>在Python3.3中,上述两个函数都将返回1。</p>
<p>Unicode字符也可以由组合代码单元组成,例如<code>é</code>。<code>normalize</code>函数可用于生成组合形式或分解形式:</p>
<pre><code>>>> import unicodedata as ud
>>> ud.name(u'\xe9')
'LATIN SMALL LETTER E WITH ACUTE'
>>> ud.normalize('NFD',u'\xe9')
u'e\u0301'
>>> ud.normalize('NFC',u'e\u0301')
u'\xe9'
</code></pre>
<p>因此,即使在Python3.3中,一个显示字符也可以有一个或多个代码单元,为了得到一致的答案,最好将其规范化为一种或另一种形式。</p>
<h3>问题2的答案:</h3>
<p>文件顶部声明的编码必须与保存文件的编码一致。声明让Python知道如何解释文件中的字节。</p>
<p>例如,字符<code>严</code>在另存为UTF-8的文件中保存为3个字节,但在另存为GBK的文件中保存为2个字节:</p>
<pre><code>>>> u'严'.encode('utf8')
'\xe4\xb8\xa5'
>>> u'严'.encode('gbk')
'\xd1\xcf'
</code></pre>
<p>如果声明了错误的编码,则字节将被错误地解释,Python将显示错误的字符或引发异常。</p>
<p><strong>按评论编辑</strong></p>
<p><strong>2(1)</strong>-这取决于系统,因为ANSI是系统区域设置的默认编码。在我的系统中,<code>cp1252</code>和记事本++不能显示中文字符。如果我将系统区域设置设置为<code>Chinese(PRC)</code>,那么我将在控制台终端上获得您的结果。在这种情况下,它正常工作的原因是使用了字节字符串,并且字节只是发送到终端。由于文件是在<code>Chinese(PRC)</code>区域设置的<code>ANSI</code>中编码的,因此<code>Chinese(PRC)</code>区域设置终端会正确解释字节字符串包含的字节。</p>
<p><strong>2(2)</strong>-文件用UTF-8编码,但编码声明为GBK。当Python读取编码时,它试图将文件解释为GBK,但失败了。您选择了<code>UTF-8</code>作为编码,在记事本++中,它还包括一个UTF-8编码字节顺序标记(BOM)作为文件中的第一个字符,而GBK编码解码器没有将其作为有效的GBK编码字符读取,因此在第1行失败。</p>
<p><strong>2(3)</strong>-文件使用UTF-8编码(带物料清单),但缺少编码声明。Python识别UTF-8编码的BOM并使用UTF-8作为编码,但是文件是GBK格式的。因为使用了字节字符串,所以UTF-8编码的字节被发送到GBK终端,您将得到:</p>
<pre><code>>>> u'严'.encode('utf8').decode(
'\xe4\xb8\xa5'
>>> '\xe4\xb8'.decode('gbk')
u'\u6d93'
>>> print '\xe4\xb8'.decode('gbk')
涓
</code></pre>
<p>在这种情况下,我很惊讶,因为Python忽略了字节<code>\xa5</code>,正如您在下面看到的,当我显式解码错误时,Python抛出一个异常:</p>
<pre><code>>>> u'严'.encode('utf8').decode('gbk')
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
UnicodeDecodeError: 'gbk' codec can't decode byte 0xa5 in position 2: incomplete multibyte sequence
</code></pre>
<p><strong>2(4)</strong>-在这种情况下,编码是ANSI(GBK),但没有声明编码,而且在UTF-8中没有类似BOM的BOM来给Python一个提示,因此它采用ASCII,并且不能处理第3行的GBK编码字符。</p>