1

我对 python 2.7 中的编码有一些疑问。

1.python代码如下,

#s = u"严"
s = u'\u4e25'
print 's is:', s
print 'len of s is:', len(s)
s1 = "a" + s
print 's1 is:', s1
print 'len of s1 is:', len(s1)

输出是:

s is: 严
len of s is: 1
s1 is: a严
len of s1 is: 2

我很困惑,为什么 lens是 1,怎么能4e25存储在 1 个字节中?我还注意到 USC-2 是 2 字节长,USC-4 是 4 字节长,为什么 unicode strings的长度是 1?

2. (1)新建一个以a.pynotepad++(Windows 7)命名的文件,并设置文件的编码ANSI,代码a.py如下:

# -*- encoding:utf-8 -*-
import sys
print sys.getdefaultencoding()
s = "严"
print "s:", s
print "type of s:", type(s)

输出是:

ascii
s: 严
type of s: <type 'str'>

(2)新建一个以b.pynotepad++(Windows 7)命名的文件,并设置文件的编码UTF-8,代码b.py如下:

# -*- encoding:gbk -*-
import sys
print sys.getdefaultencoding()
s = "严"
print "s:", s
print "type of s:", type(s)

输出是:

  File "D:\pyws\code\\b.py", line 1
SyntaxError: encoding problem: utf-8

(3)修改文件b.py如下(文件的编码风格为UTF-8):

import sys
print sys.getdefaultencoding()
s = "严"
print "s:", s
print "type of s:", type(s)

输出是:

ascii
s: 涓
type of s: <type 'str'>

(4)修改文件a.py如下(文件编码风格为ANSI):

import sys
print sys.getdefaultencoding()
s = "严"
print "s:", s
print "type of s:", type(s)

输出是:

  File "D:\pyws\code\a1.py", line 3
SyntaxError: Non-ASCII character '\xd1' in file D:\pyws\code\a1.py on
line 3, but no encoding declared; see http://www.python.org/peps/pep-0263.html f
or details

为什么问题 2 中这 4 个案例的输出不同?任何人都可以详细弄清楚吗?

4

2 回答 2

5

我很困惑为什么 s 的 len 是 1,4e25 怎么能存储在 1 个字节中?我还注意到 USC-2 是 2 字节长,USC-4 是 4 字节长,为什么 unicode 字符串 s 的长度是 1?

unicode 字符串的全部意义在于做到这一点。unicode 字符串的长度是字符数(即代码点),而不是字节数。字节数可能因编码而异,但字符数是一个抽象不变量,不会随编码而改变。

至于您的第二个问题,答案是在设置文件的编码时,您是在告诉 Python 如何将该文件中的字节映射到字符。如果您指定的编码(使用# encoding语法)与文件的实际编码不一致,您将得到不可预知的行为,因为 Python 试图以一种方式解释字节,但文件已设置,因此字节实际上意味着其他东西。

您获得的行为类型将取决于您使用的编码的细节。一些可能性是:

  1. 你会很幸运,即使你使用了冲突的编码,它也会起作用;这是您的第一个案例中发生的情况。
  2. 会报错,因为文件中的字节与指定的编码不一致;这就是你的第二种情况发生的事情。
  3. 它似乎可以工作,但会产生不同的字符,因为文件实际编码中的字节在用指定的编码解释时意味着其他东西。这似乎是您的第三种情况发生的情况,尽管它应该引发错误,因为该字符不是 ASCII。(“文件的编码样式是 UTF-8”是指您# encoding在文件中设置了该效果的指令吗?)
  4. 如果您未指定任何编码,则如果您尝试使用任何非纯 ASCII 字节,则会收到错误消息。这就是你上一个案例中发生的情况。

此外,字符串的类型str在所有情况下都是,因为您没有将字符串指定为 unicode(例如,with u"...")。指定文件编码不会使字符串成为 unicode。它只是告诉 Python 如何解释文件中的字符。

然而,这里有一个更大的问题,那就是:为什么在你的例子中玩那些带有编码的游戏?除了文件实际编码的编码之外,没有任何理由使用# encoding标记来指定编码,这样做肯定会导致问题。不要这样做。您必须知道文件的编码是什么,并在# encoding标记中指定相同的编码。

于 2012-10-19T08:31:48.107 回答
1
于 2012-10-19T18:02:29.137 回答