如何使用表示为Unicode的Python对象列表

4 投票
7 回答
8396 浏览
提问于 2025-04-15 11:28

我有一个包含Unicode数据的对象,我想在它的表示中使用这些数据,比如:

# -*- coding: utf-8 -*-

class A(object):

    def __unicode__(self):
        return u"©au"

    def __repr__(self):
        return unicode(self).encode("utf-8")

    __str__ = __repr__ 

a = A()


s1 = u"%s"%a # works
#s2 = u"%s"%[a] # gives unicode decode error
#s3 = u"%s"%unicode([a])  # gives unicode decode error

现在,即使我从repr返回Unicode,它仍然会出错。所以我的问题是,如何使用这样一系列对象,并从中创建另一个Unicode字符串呢?

平台信息:

"""
Python 2.5.2 (r252:60911, Jul 31 2008, 17:28:52)
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
'Linux-2.6.24-19-generic-i686-with-debian-lenny-sid'
""" 

我也不太确定为什么会这样。

print a # works
print unicode(a) # works
print [a] # works
print unicode([a]) # doesn't works 

关于这个问题,Python的讨论组有一些答案,链接在这里: http://groups.google.com/group/comp.lang.python/browse_thread/thread/bd7ced9e4017d8de/2e0b07c761604137?lnk=gst&q=unicode#2e0b07c761604137

7 个回答

2

首先,问问自己你想要达到什么目的。如果你只是想要一个可以来回转换的列表表示方式,你只需要这样做:

class A(object):
    def __unicode__(self):
        return u"©au"
    def __repr__(self):
        return repr(unicode(self))
    __str__ = __repr__

>>> A()
u'\xa9au'
>>> [A()]
[u'\xa9au']
>>> u"%s" % [A()]
u"[u'\\xa9au']"
>>> "%s" % [A()]
"[u'\\xa9au']"
>>> print u"%s" % [A()]
[u'\xa9au']

这就是它应该工作的方式。Python 列表的字符串表示并不是用户应该看到的内容,所以在其中使用转义字符是有道理的。

3

试试这个:

s2 = u"%s"%[unicode(a)] 

你主要的问题是,你进行的转换比你想象的要多。我们来看看下面的内容:

s2 = u"%s"%[a] # gives unicode decode error

来自 Python 文档

    's'     String (converts any python object using str()).
    If the object or format provided is a unicode string, 
    the resulting string will also be unicode.

当处理 %s 格式字符串时,会应用 str([a])。此时你得到的是一个字符串对象,它包含了一串 Unicode 字节。如果你尝试打印这个字符串,是没有问题的,因为这些字节直接通过终端显示出来,终端会把它们渲染出来。

>>> x = "%s" % [a]
>>> print x
[©au]

问题出现在你试图将其转换回 Unicode 时。实际上,函数 unicode 是在包含 Unicode 编码字节序列的字符串上被调用的,这就是导致 ascii 编解码器失败的原因。

    >>> u"%s" % x
    Traceback (most recent call last):
      File "", line 1, in 
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 1: ordinal not in range(128)
    >>> unicode(x)
    Traceback (most recent call last):
      File "", line 1, in 
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 1: ordinal not in range(128)
4

s1 = u"%s"%a # 可以正常工作

这个可以正常工作,因为在处理'a'的时候,它使用的是'a'的unicode表示(也就是unicode方法)。

但是,当你把'a'放到一个列表里,比如说'[a]',然后试图把这个列表放进字符串里时,实际上调用的是unicode([a])(在列表的情况下,这和repr是一样的),也就是列表的字符串表示。这个表示会用'repr(a)'来显示你列表里的元素。这就会造成问题,因为你传递的是一个'str'对象(一个字节字符串),里面包含了'a'的utf-8编码版本。当字符串格式试图把这个放进你的unicode字符串时,它会尝试用默认编码(也就是ASCII)把它转换回unicode对象。由于ASCII不包含它要转换的字符,所以就失败了。

你想要做到的应该这样做:u"%s" % repr([a]).decode('utf-8'),假设你所有的元素都能编码成utf-8(或者ASCII,因为从unicode的角度看,ASCII是utf-8的一个子集)。

如果你想让字符串看起来像一个列表字符串,使用之前提到的方法,结合join,可以这样写:

u'[%s]' % u','.join(unicode(x) for x in [a,a])

不过,这样做并不能处理包含你的A对象列表的列表。

我的解释可能听起来很模糊,但我希望你能理解其中的一些意思。

撰写回答