我希望我的函数接受一个可能是unicode对象或utf-8编码字符串的参数。在我的函数中,我想将参数转换为unicode。我有这样的事情:
def myfunction(text):
if not isinstance(text, unicode):
text = unicode(text, 'utf-8')
...
是否可以避免使用isinstance?我正在寻找更友善的鸭子。
在我的解码实验中,我遇到了几种奇怪的Python行为。例如:
>>> u'hello'.decode('utf-8')
u'hello'
>>> u'cer\xf3n'.decode('utf-8')
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/usr/lib/python2.6/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in po
sition 3: ordinal not in range(128)
或者
>>> u'hello'.decode('utf-8')
u'hello' 12:11
>>> unicode(u'hello', 'utf-8')
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: decoding Unicode is not supported
顺便说一下。我正在使用Python 2.6
答案 0 :(得分:18)
您可以尝试使用'utf-8'编解码器对其进行解码,如果这不起作用,则返回该对象。
def myfunction(text):
try:
text = unicode(text, 'utf-8')
except TypeError:
return text
print(myfunction(u'cer\xf3n'))
# cerón
当您使用unicode对象并使用decode
编解码器调用其'utf-8'
方法时,Python首先尝试将unicode对象转换为字符串对象,然后调用字符串对象的解码(' utf-8')方法。
有时从unicode对象到字符串对象的转换失败,因为Python2默认使用ascii编解码器。
因此,一般来说,永远不要尝试解码unicode对象。或者,如果必须尝试,请将其捕获到try..except块中。可能有一些编解码器解码unicode对象在Python2中工作(见下文),但它们已在Python3中删除。
有关此问题的有趣讨论,请参阅此Python bug ticket, 还有Guido van Rossum's blog:
“我们采用的略有不同 编解码器的方法:在Python 2中, 编解码器可以接受Unicode或 8位作为输入并产生为 输出,在Py3k中,编码总是一个 从Unicode(文本)翻译 字符串到一个字节数组,和 解码总是相反的 方向。这意味着我们必须这样做 删除一些不适合的编解码器 这个模型,例如rot13,base64 和bz2(那些转换仍然是 支持,只是不通过 编码/解码API)。“
答案 1 :(得分:0)
我不知道有什么好方法可以避免isinstance
检查你的功能,但也许其他人会这样做。我可以指出,你引用的两个奇怪之处是因为你正在做一些没有意义的事情:尝试将已解码为Unicode的Unicode解码。
第一个应该是这样的,它将该字符串的UTF-8编码解码为Unicode版本:
>>> 'cer\xc3\xb3n'.decode('utf-8')
u'cer\xf3n'
你的第二个应该是这样的(不使用u''
Unicode字符串文字):
>>> unicode('hello', 'utf-8')
u'hello'