🐈

Pythonのstr.translateは単一文字列を引数に取れるらしい

2022/04/29に公開

TL;DR

Pythonのstr.translateは文字列を引数に取れる

ブラックボックス的に触った感じのおそらくの挙動

a.translate(b)(a, bはstr)としたとき

    res = ""
    for c in s:
        try:
            res += b[ord(c)] 
        except:
            res += c
    return res

予想した論理的な挙動を書いているだけでこういうコードではまったくないと思います。
(例外をこんな風に使うのはバットプラクティスであることは自覚していますが、簡潔に書きたかったので上記のように書いています)

顛末

サイバーセキュリティプログラミング[1]を読んでいるときに、
以下のようなアスキー文字列を印字可能な文字列に変換するという処理に出会いました。

HEX_FILTER = ''.join([(len(repr(chr[i])) == 3) and chr(i) or '.' for i in range(256)])

printable = word.translate(HEX_FILTER)

pythonにはtranslateっていう便利な関数があるんやなあ(Python素人並感)という感想を抱きWebでググると
translateの引数に文字列を一つ指定するという使い方を明記しているものに出会えませんでした。

https://note.nkmk.me/python-str-replace-translate-re-sub/
https://hibiki-press.tech/python/str-translate/5322
https://qiita.com/tag1216/items/df6c93bdb823dd48af6c

ん?と思いながら信頼の公式ドキュメントをみると、以下のような記載がありました。

与えられた変換テーブルに基づいて文字列を構成する各文字をマッピングし、マッピング後の文字列のコピーを返します。変換テーブルは、__getitem__() によるインデックス指定を実装するオブジェクトである必要があります。一般的には、 mapping または sequence です。Unicode 序数 (整数) でインデックス指定する場合、変換テーブルのオブジェクトは次のいずれも行うことができます。Unicode 序数または文字列を返して文字を 1 文字以上の別の文字にマッピングすること、None を返して返り値の文字列から指定した文字を削除すること、例外 LookupError を送出して文字をその文字自身にマッピングすること。

文字から文字への異なる形式のマッピングから変換マップを作成するために、 str.maketrans() が使えます。

文字のマッピングを好みに合わせてより柔軟に変更する方法については、codecs モジュールも参照してください。
https://docs.python.org/ja/3/library/stdtypes.html?highlight=translate#str.translate より引用

ほお、__getitem__()なるものを実装しているオブジェクトならいいのかと思い、__getitem__()とは何かと調べると__getitem__()はオブジェクトに角括弧にアクセスしたときの挙動を定義できる。とありました。

にゃるほど、と思いましたが、文字列に文字でインデックスアクセスすることはできません。じゃあordで変換した値でアクセスしているのかと思い実験していみるとどうやらそうっぽいとなった次第です。

ord("a")
# 97
b = "0"*97 + "A" + "0"
#'0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A0' 
a = "a"
a.translate(b)
# 'A'
脚注
  1. ワイみたいなアホにはちょっと難しいですが、大変良い本です。 ↩︎

GitHubで編集を提案

Discussion