2009-08-24 47 views
54

我有以下代碼:如何獲得str.translate以使用Unicode字符串?

import string 
def translate_non_alphanumerics(to_translate, translate_to='_'): 
    not_letters_or_digits = u'!"#%\'()*+,-./:;<=>[email protected][\]^_`{|}~' 
    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 

我不能做任何對str.translate()方法的Python 2.6.2 docs中的「Unicode對象」的段落感。

如何使Unicode字符串工作?

+0

這是一個[使用'unicode.translate()'方法](http://stackoverflow.com/a/11066687/4279)從字符串中刪除Unicode標點符號的示例。 – jfs 2013-12-21 03:24:23

+0

更好用'import string; string.punctuation'而不是在實際代碼中硬編碼'not_letters_or_digits'。在這裏我明白你的意思。 – 2016-02-29 11:48:48

回答

50

Unicode版本的translate需要從Unicode序號(您可以檢索單個字符ord)到Unicode序號的映射。如果要刪除字符,請將其映射到None

我改變你的函數建立字典的每個字符的順序映射到你想翻譯什麼的序:

def translate_non_alphanumerics(to_translate, translate_to=u'_'): 
    not_letters_or_digits = u'!"#%\'()*+,-./:;<=>[email protected][\]^_`{|}~' 
    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字符串或無(要刪除)。因此,我已將translate_to的默認值更改爲Unicode字面值。例如:

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

謝謝! (這樣的愚蠢的設計決定有一個命名相同的函數,其運行方式不同。) – Sabuncu 2012-05-11 15:03:01

+1

另外,如果您不想手動定義標點符號:import string; translate_table = {ord(unicode(c))for c in string.punctuation} 注意:這不會翻譯所有特殊的unicode標點字符(有噸......) – dpb 2016-05-10 17:33:31

+0

您的'not_letters_or_digits'缺少'$'和'&'。讓我建議使用'string.punctuation'而不是硬編碼集或字符 – 2017-05-17 09:31:27

5

我想到了我的原函數的下列組合和Mike的版本與Unicode和ASCII字符串的工作原理:

def translate_non_alphanumerics(to_translate, translate_to=u'_'): 
    not_letters_or_digits = u'!"#%\'()*+,-./:;<=>[email protected][\]^_`{|}~' 
    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。謝謝邁克。

+0

我建議你強制translate_to爲Unicode版本的Unicode,否則如果你通過一個Unicode字符串翻譯調用會嚇壞了,「正常「字符串。 – 2009-08-24 19:40:05

+0

這看起來應該是該語言的一部分。 +1 – bukzor 2010-04-24 16:39:33

4

對於一個簡單的黑客,這將在兩個海峽和Unicode對象工作, 轉換的轉換表爲Unicode運行翻譯()之前:

import string 
def translate_non_alphanumerics(to_translate, translate_to='_'): 
    not_letters_or_digits = u'!"#%\'()*+,-./:;<=>[email protected][\]^_`{|}~' 
    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字符則拋出錯誤。

0

而不必指定需要更換的所有字符的,你也可以查看周圍它的其他方式,相反,僅指定有效的字符,像這樣:

import re 

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

    return result 

這適用於unicode以及常規字符串,並保留該類型(如果replacement_charactersource顯然都是相同類型的話)。

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

我發現,凡在蟒蛇2。7,具有str類型,你會寫

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

而與類型unicode你會說

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

在蟒蛇3.6你會寫

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

也許這是有幫助的。

相關問題