使用unicode字符迭代字符串时,字符串字符被误解释

时间:2013-06-01 02:13:38

标签: python python-2.7 utf-8 character-encoding

我在mac os x 10.6上运行python 2.7,文件在utf8,终端在utf8。

我想在每次出现在给定字符串中的元音å,ä或ö之后添加句点。

以下是我想要做的愚蠢版本:

# coding: utf8

a = 'change these letters äöå'

b = map( (lambda x: a.replace(x, "{0}.".format(x))), 'åäö')

for c in b:
    print c

产生以下输出:

change these letters ?.??.??.?
change these letters äöå.
change these letters ?.??.??.?
change these letters ä.öå
change these letters ?.??.??.?
change these letters äö.å

为什么我会带问号线?经过进一步研究,这样做会产生相同的问号。

# coding: utf8

for letter in 'åäö':
    print letter

输出:

?
?
?
?
?
?

但是明确地添加u之前给出了

# coding: utf8
for letter in u'åäö':
    print letter

输出:

å
ä
ö

将字符串明确解码并编码回utf8仍会产生问号。这里有什么问题?什么在这个循环中徘徊?

旁注:在愚蠢的例子中,你会看到我想要做的事情。实际上我正在使用一个保存字符串的对象,以便映射的操作发生在同一个字符串上。因此,map()调用实际上每次使用一个新元音调用对象的方法,从而更新保存在对象中的字符串。对象的方法使用map的第二个参数中的元音执行替换,并更新存储的字符串。

2 个答案:

答案 0 :(得分:2)

您将匿名函数映射到字符串上;你应该将它映射到字符串列表。 Python解释器仍将接受您提供的指令,将字符串视为序列并将lambda应用于该序列的每个组件。但在这种情况下,组件是字符串的单个字节,每个unicode字符都是两个字节。所以替换执行六次。

此外,在这些迭代中的三个中,替换是用0xc3替换unicode前缀字节äöå(在0xc3.中发生三次)的相同操作,这打破了字符串a中的字符编码并生成原始字节乱码。在其他三次迭代中,您将unicode char的第二个字节替换为该字节后跟一个句点,因此生成的字符串仍包含相关字符的字节序列,您将获得所需的结果。但那是而不是,因为你用一个字符替换整个字符后跟一段时间。

比较

>>> a = 'change these letters äöå'
>>> b = map( (lambda x: a.replace(x, "{0}.".format(x))), 'å ä ö'.split())
>>> for c in b:
...   print c
... 
change these letters äöå.
change these letters ä.öå
change these letters äö.å

答案 1 :(得分:1)

您正在迭代字节字符串中的字节。由于编码为UTF-8的非ASCII字符使用多个字节,因此您将破坏字符。如果必须遍历字符,则迭代unicode的字符。