如何获得str.translate使用Unicodestring?

我有以下代码:

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) 

这对于非Unicodestring非常有用:

 >>> translate_non_alphanumerics('<foo>!') '_foo__' 

但unicodestring失败:

 >>> 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 

对于str.translate()方法的Python 2.6.2文档中的“Unicode对象”的段落,我无法理解。

我如何使这个工作的Unicodestring?

Unicode版本的translate需要从Unicode序号(您可以通过ord检索单个字符)映射到Unicode序号。 如果要删除字符,则映射到“ None

我改变了你的函数来build立一个字典映射每个字符的序数到你想要翻译的序数:

 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__' 

编辑:事实certificate,翻译映射必须从Unicode序号(通过ord )映射到另一个Unicode序号,Unicodestring或None(要删除)。 因此,我将translate_to的默认值更改为Unicode字面值。 例如:

 >>> translate_non_alphanumerics(u'<foo>!', u'bad') u'badfoobadbad' 

在这个版本中,你可以相对地给其他人写信

 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) 

我想到了我的原始函数和Mike的Unicode和ASCIIstring的版本的以下组合:

 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。

对于可以在str和unicode对象上工作的简单hack,在运行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)) translate_table = translate_table.decode("latin-1") return to_translate.translate(translate_table) 

这里的问题是,它会隐式地将所有str对象转换为unicode,如果to_translate包含非ascii字符则抛出错误。

不必指定所有需要replace的字符,也可以用相反的方法查看它,而只指定有效的字符,如下所示:

 import re def replace_non_alphanumerics(source, replacement_character='_'): result = re.sub("[^_a-zA-Z0-9]", replacement_character, source) return result 

这与unicode以及常规string一起工作,并保留该types(如果replacement_charactersource显然是同一types的话)。

我发现,在Python 2.7中,typesstr ,你会写

 import string table = string.maketrans("123", "abc") print "135".translate(table) 

而与typesunicode你会说

 table = {ord(s): unicode(d) for s, d in zip("123", "abc")} print u"135".translate(table) 

在Python 3.6中,你会写

 table = {ord(s): d for s, d in zip("123", "abc")} print("135".translate(table)) 

也许这是有帮助的。