使用 vanilla Python 库进行字符到子串的翻译
Character-to-substring translation using vanilla Python libraries
问题
仅使用 vanilla Python 2.x(其中 x >= 7)内置的模块和函数,而无需滚动我自己的 Python 函数来执行此操作(见下文),如何将字符翻译成类似于 urllib.quote(), but limited to a subset of the characters that urllib.quote() 翻译的字符串?
在下面的示例中,它正在进行 url 编码,但我的问题恰好比 url 编码更基本和更笼统。在一般情况下,我想将任意指定的字符转换为任意指定的字符串,而不仅仅是那些符合 url 编码的 RFC 合规性。
例子
在下面的示例中,我只翻译平衡的括号字符(方括号、curly 括号和圆括号),而不是所有其他需要为 [=69= 引用的字符] 查询字符串。这根本与网络无关,而是针对 Python 脚本生成的输出的 paren navigation。
我想我可以使用一些看起来既简洁又高效的东西,它将内置到 vanilla Python 2.x(vanilla 不需要安装额外的模块)使用类似于 string translate,但后者要求翻译 table 是从单个字符到单个字符的映射,而不是我想要的从单个字符到多个字符串的映射。
所以我在下面写了自己的:
def urlencode_parens(line):
"""url encode parens as would urllib.quote would do, but we only want it for parens"""
trans_table = {
'(': '%28',
')': '%29',
'{': '%7B',
'}': '%7D',
'[': '%5B',
']': '%5D',
}
retval = []
for char in line:
if char in trans_table:
char = trans_table[char]
retval.append(char)
return "".join(retval)
虽然基本的时序分析显示上面的速度非常快,但让我感到困扰的是我必须首先将其编码(因为现在我必须将其隐藏在我自己的个人模块集中并维护它).
我尝试过的东西
我调查了如何将 urllib.quote() 强制转换为 仅 翻译上述字符,但它似乎在内部硬编码了这些字符的翻译而没有任何方法 extend/customize它。
我可以使用 re.sub() 来做到这一点,但我必须将它们链接起来,无论如何,考虑到 Python 中字符串的不变性。它导致代码看起来更像 Lisp 而不是 Python(不是说 Lisp 不好,只是 "When in Rome ... etc.")。鉴于正则表达式翻译可能涉及对正则表达式的重复重新编译,我放弃了它,因为我认为它的性能可能不如我上面编写的那样。
更新#1:maketrans 文档字符串具有误导性and/or不正确
看着 string.maketrans 我明白了:
这给出 no 指示 to
参数是可选的。它也没有说明如何使用 from
字段,正如 答案所指出的那样。
在 python 3 你可以这样做:
如果你只传递一个参数给str.maketrans
(一个映射字典)你也可以有多个字符:
trans_dict = {
'(': '%28',
')': '%29',
'{': '%7B',
'}': '%7D',
'[': '%5B',
']': '%5D',
}
trans_table = str.maketrans(trans_dict)
print('dict={} tuple=()'.translate(trans_table))
# dict=%7B%7D tuple=%28%29
在 python 2.7 你可以尝试使用 unicode.translate
:
trans_dict = {
'(': '%28',
')': '%29',
'{': '%7B',
'}': '%7D',
'[': '%5B',
']': '%5D',
}
trans_table = {ord(char): unicode(repl) for char, repl in trans_dict.items()}
print(u'dict={} tuple=()'.translate(trans_table))
问题
仅使用 vanilla Python 2.x(其中 x >= 7)内置的模块和函数,而无需滚动我自己的 Python 函数来执行此操作(见下文),如何将字符翻译成类似于 urllib.quote(), but limited to a subset of the characters that urllib.quote() 翻译的字符串?
在下面的示例中,它正在进行 url 编码,但我的问题恰好比 url 编码更基本和更笼统。在一般情况下,我想将任意指定的字符转换为任意指定的字符串,而不仅仅是那些符合 url 编码的 RFC 合规性。
例子
在下面的示例中,我只翻译平衡的括号字符(方括号、curly 括号和圆括号),而不是所有其他需要为 [=69= 引用的字符] 查询字符串。这根本与网络无关,而是针对 Python 脚本生成的输出的 paren navigation。
我想我可以使用一些看起来既简洁又高效的东西,它将内置到 vanilla Python 2.x(vanilla 不需要安装额外的模块)使用类似于 string translate,但后者要求翻译 table 是从单个字符到单个字符的映射,而不是我想要的从单个字符到多个字符串的映射。
所以我在下面写了自己的:
def urlencode_parens(line):
"""url encode parens as would urllib.quote would do, but we only want it for parens"""
trans_table = {
'(': '%28',
')': '%29',
'{': '%7B',
'}': '%7D',
'[': '%5B',
']': '%5D',
}
retval = []
for char in line:
if char in trans_table:
char = trans_table[char]
retval.append(char)
return "".join(retval)
虽然基本的时序分析显示上面的速度非常快,但让我感到困扰的是我必须首先将其编码(因为现在我必须将其隐藏在我自己的个人模块集中并维护它).
我尝试过的东西
我调查了如何将 urllib.quote() 强制转换为 仅 翻译上述字符,但它似乎在内部硬编码了这些字符的翻译而没有任何方法 extend/customize它。
我可以使用 re.sub() 来做到这一点,但我必须将它们链接起来,无论如何,考虑到 Python 中字符串的不变性。它导致代码看起来更像 Lisp 而不是 Python(不是说 Lisp 不好,只是 "When in Rome ... etc.")。鉴于正则表达式翻译可能涉及对正则表达式的重复重新编译,我放弃了它,因为我认为它的性能可能不如我上面编写的那样。
更新#1:maketrans 文档字符串具有误导性and/or不正确
看着 string.maketrans 我明白了:
这给出 no 指示 to
参数是可选的。它也没有说明如何使用 from
字段,正如
在 python 3 你可以这样做:
如果你只传递一个参数给str.maketrans
(一个映射字典)你也可以有多个字符:
trans_dict = {
'(': '%28',
')': '%29',
'{': '%7B',
'}': '%7D',
'[': '%5B',
']': '%5D',
}
trans_table = str.maketrans(trans_dict)
print('dict={} tuple=()'.translate(trans_table))
# dict=%7B%7D tuple=%28%29
在 python 2.7 你可以尝试使用 unicode.translate
:
trans_dict = {
'(': '%28',
')': '%29',
'{': '%7B',
'}': '%7D',
'[': '%5B',
']': '%5D',
}
trans_table = {ord(char): unicode(repl) for char, repl in trans_dict.items()}
print(u'dict={} tuple=()'.translate(trans_table))