【Python】詳解 str.maketrans() (附 Unicode 碼速查表)

目錄

一、說明

1.1 函數原型

1.2 dict 操作

1.3 string 操作

二、典例 —— 字符串解密

三、附錄 —— Unicode 碼速查表


一、說明

1.1 函數原型

static str.maketrans(x[, y[, z]) 

此靜態方法返回一個可供 str.translate() 使用的轉換對照表

注意:Python3.4+ 已移除 string.maketrans(),由內建函數 bytearray.maketrans()、bytes.maketrans()、str.maketrans() 替代。

1.2 dict 操作

若只輸入1個參數 x,則 x 必須是一個將 Unicode 碼位序號 (int) 或字符 (長度爲1的 string) 映射到 Unicode 碼位序號、(任意長度的)字符串或 None 的字典。 注意,若輸入字典 x 的 key 爲字符,則輸出字典的 key 會被轉換爲 Unicode 碼位序號。例如:

>>> dict0 = {'a': 1, 'b': 2, 'c': 3}  # key 爲字符 (長度爲1的 string) 
>>> str.maketrans(dict0)  # ord('a')=97, ord('b')=98, ord('c')=99            
{97: 1, 98: 2, 99: 3}
# ---------------------------------------------------------------------
>>> dict1 = {10: 1, 11: 2, 12: 3}  # key 爲 Unicode 碼位序號 (int)
>>> str.maketrans(dict1)  # key 類型爲 int 輸出不變
{10: 1, 11: 2, 12: 3}
# ---------------------------------------------------------------------
>>> dict2 = {'n': None, '0': None, 0: None}  # key 混合類型
>>> str.maketrans(dict2)  # ord('n')=110, ord('0')=48
{110: None, 48: None, 0: None}

但該操作並不常用。

1.3 string 操作

若輸入2個參數,則二者必須爲 長度相等且一一對應的字符串,此時該方法用於 創建字符映射的轉換表。其中 x 是待轉換字符串y 是轉換目標字符串。該方法輸出一個字典, 其中 x 中每個字符將被映射到 y 中相同位置的字符。例如:

>>> in_table = 'ab'
>>> out_table = '12'
>>> trans_table = str.maketrans(in_table, out_table)
>>> trans_table
{97: 49, 98: 50}

輸出字典中,key 是 x 中字符的 Unicode 碼位序號, value 是 y 中字符的 Unicode 碼位序號,驗證如下:

>>> ord('a')
97
>>> ord('b')
98
>>> ord('1')
49
>>> ord('2')
50

如果 x 中存在重複的字符,則自動選用索引最大的字符來映射:

>>> in_table = 'abb'
>>> out_table = '123'  # ord('1')=49, ord('1')=50, ord('1')=51
>>> trans_table = str.maketrans(in_table, out_table)
>>> trans_table  # 可見對於重複的 key, 選用的了索引更大(位置更靠後)的
{97: 49, 98: 51}

此外,若輸入第3個參數 z,則它必須是一個字符串,其中的字符將在輸出字典中被映射到 None。例如:

>>> in_table = 'ab'
>>> out_table = '12'
>>> other_table = 'yz'  # ord('y')=121, ord('z')=122
>>> trans_table = str.maketrans(in_table, out_table, other_table)
>>> trans_table
{97: 49, 98: 50, 121: None, 122: None}

二、典例 —— 字符串解密

該例子改編自 Python Challenge-2。給出一個句子,解密方法是:讀取每個字母的 ASCII 碼 +2 後的字母組成的句子:

g fmnc wms bgblr rpylqjyrc gr zw fylb.

根據該轉換關係,很容易想到利用內建函數 ord() 將字母轉換成 ASCII 碼、chr() 將相對應的 ASCII 碼轉化爲字母,然後依次遍歷字符串中的字符轉化:

>>> text = """g fmnc wms bgblr rpylqjyrc gr zw fylb."""

>>> def solution1(text):
	result = ""
	for each in text:
		if ord(each) >= ord('a') and ord(each) <= ord('z'):
            # 因爲 ord('y')=121, ord('z')=122, ord('{')=123, ord('|')=124
            # 故應確保 'y' 和 'z' 的 ASCII 碼 +2 後應循環恢復爲 'a' 和 'b'
			result += chr((ord(each) + 2 - ord('a')) % 26 + ord('a'))
		else:
			result += each
	print(result)

>>> solution1(text)  # 轉換解碼
i hope you didnt translate it by hand.

但實際上,Python 提供了更爲便捷的解決方式 —— 使用 str.maketrans() + str.translate() 方法,如下所示:

import string

text = """g fmnc wms bgblr rpylqjyrc gr zw fylb."""

>>> def solution2(text):
    table = str.maketrans(
            string.ascii_lowercase,  # 26 個小寫字母 a-z
            string.ascii_lowercase[2:] + string.ascii_lowercase[:2])  # c-z 接上 a-b
    print(table)
    print(text.translate(table))

>>> solution2(text)
{97: 99, 98: 100, 99: 101, 100: 102, 101: 103, 102: 104, 103: 105, 104: 106, 105: 107, 106: 108, 107: 109, 108: 110, 109: 111, 110: 112, 111: 113, 112: 114, 113: 115, 114: 116, 115: 117, 116: 118, 117: 119, 118: 120, 119: 121, 120: 122, 121: 97, 122: 98}
i hope you didnt translate it by hand.

可見,輸出 dict 中均爲 Unicode 碼位序號構成的 key:value 對。其中,key 是 26 個小寫字母 a-z 的 Unicode 碼位序號,value 則是 key 的 Unicode 碼位序號 +2,對應 b-z 接上 a-b 這 26 個字母 (相當於右循環移2步)。

最後,使用 string.translate() 方法,根據映射規則表 table,將密語 text  “翻譯/轉換” 爲解密語 string 。

三、附錄 —— Unicode 碼速查表

上表來自百度百科。


參考文獻

http://www.pythonchallenge.com/pc/def/map.html

https://www.runoob.com/python3/python3-string-maketrans.html

https://docs.python.org/zh-cn/3.6/library/stdtypes.html?highlight=maketrans#str.maketrans

https://docs.python.org/zh-cn/3.6/library/stdtypes.html?highlight=maketrans#str.translate

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章