如何使str.translate与Unicode字符串一起工作?
我有以下这段代码:
import string
def translate_non_alphanumerics(to_translate, translate_to='_'):
not_letters_or_digits = u'!"#%\'()*+,-./:;<=>?@[\]^_`{|}~'
translate_table = string.maketrans(not_letters_or_digits,
translate_to
*len(not_letters_or_digits))
return to_translate.translate(translate_table)
这段代码对非Unicode字符串效果很好:
>>> translate_non_alphanumerics('<foo>!')
'_foo__'
但是对Unicode字符串就不行了:
>>> translate_non_alphanumerics(u'<foo>!')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in translate_non_alphanumerics
TypeError: character mapping must return integer, None or unicode
我看不懂在Python 2.6.2文档中关于“Unicode对象”的那段话,特别是关于str.translate()方法的部分。
我该如何让这段代码也能处理Unicode字符串呢?
7 个回答
5
我想出了一个结合我自己原来的函数和Mike版本的办法,这个办法可以同时处理Unicode和ASCII字符串:
def translate_non_alphanumerics(to_translate, translate_to=u'_'):
not_letters_or_digits = u'!"#%\'()*+,-./:;<=>?@[\]^_`{|}~'
if isinstance(to_translate, unicode):
translate_table = dict((ord(char), unicode(translate_to))
for char in not_letters_or_digits)
else:
assert isinstance(to_translate, str)
translate_table = string.maketrans(not_letters_or_digits,
translate_to
*len(not_letters_or_digits))
return to_translate.translate(translate_table)
更新:把translate_to
强制转换成了Unicode,以便与Unicode的translate_table
一起使用。谢谢你,Mike。
7
在这个版本中,你可以相对地调整一个字母与其他字母之间的关系。
def trans(to_translate):
tabin = u'привет'
tabout = u'тевирп'
tabin = [ord(char) for char in tabin]
translate_table = dict(zip(tabin, tabout))
return to_translate.translate(translate_table)
58
Unicode版本的translate函数需要一个映射,这个映射是从Unicode的数字编码(你可以用ord
函数获取单个字符的编码)到Unicode的数字编码。如果你想删除某些字符,就把它们映射到None
。
我修改了你的函数,创建了一个字典,这个字典把每个字符的编码映射到你想要转换成的编码:
def translate_non_alphanumerics(to_translate, translate_to=u'_'):
not_letters_or_digits = u'!"#%\'()*+,-./:;<=>?@[\]^_`{|}~'
translate_table = dict((ord(char), translate_to) for char in not_letters_or_digits)
return to_translate.translate(translate_table)
>>> translate_non_alphanumerics(u'<foo>!')
u'_foo__'
补充:结果发现,转换映射必须是从Unicode编码(通过ord
获取)映射到另一个Unicode编码、一个Unicode字符串,或者是None(表示删除)。因此,我把translate_to
的默认值改成了一个Unicode字面量。例如:
>>> translate_non_alphanumerics(u'<foo>!', u'bad')
u'badfoobadbad'