私は次のコードを持っています:
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)
これは非ユニコード文字列に最適です:
>>> 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文字列に対してこれを機能させるにはどうすればよいですか?
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__'
edit:翻訳マッピングは、Unicode序数から(ord
を介して)別のUnicode序数、Unicode文字列、または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)
元の関数と、UnicodeとASCII文字列で動作する Mike のバージョン)の次の組み合わせを思いつきました。
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)
Update: "強制" translate_to
ユニコードのユニコードtranslate_table
。マイクありがとう。
StrオブジェクトとUnicodeオブジェクトの両方で機能する単純なハックの場合、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文字が含まれている場合にエラーをスローすることです。
置換する必要があるすべての文字を指定する代わりに、逆の方法で表示し、代わりに次のように有効な文字のみを指定することもできます。
import re
def replace_non_alphanumerics(source, replacement_character='_'):
result = re.sub("[^_a-zA-Z0-9]", replacement_character, source)
return result
これは、Unicodeと通常の文字列で機能し、タイプを保持します(両方のreplacement_character
とsource
は同じタイプです。
私は、python 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)
python 3.6で書く
table = {ord(s): d for s, d in Zip("123", "abc")}
print("135".translate(table))
多分これは役に立ちます。