使用香草Python库将字符转换为子字符串

时间:2018-07-23 14:37:05

标签: python-2.x built-in

问题

仅使用香草Python 2.x内置的模块和函数(其中x为> = 7),而无需滚动自己的Python函数(见下文),如何将字符转换为字符串类似于urllib.quote()的用法,但仅限于urllib.quote()翻译的字符的子集?

在下面的示例中,它正在执行urlencoding,但我的问题碰巧比urlencoding更基本,更笼统。在一般情况下,我想将任意指定的字符转换为任意指定的字符串,而不仅仅是将那些符合RFC的url编码转换为字符串。

示例

在下面的示例中,我仅翻译了平衡的括号中的字符(方括号,大括号和括号),而不翻译URL查询字符串中需要引用的所有其他字符。这一点与网络无关,但与Python脚本产生的输出paren navigation有关。

我认为我可以使用string translate之类的东西,将其内置到Vanilla Python 2.x中(香草不需要安装其他模块),这些东西看起来既简洁又高效。但是后者要求转换表是从单个字符到单个字符的映射,而不是我期望的从单个字符到多个字符串的映射。

所以我在下面写下了自己的内容:

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() 来翻译上述字符,但是似乎内部对这些字符的翻译进行了硬编码,而没有任何扩展/自定义的方法。

我可以使用re.sub()来做到这一点,但是鉴于Python中字符串的不变性,我必须将它们链接起来。它导致代码看起来更像Lisp,而不是Python(不是Lisp不好,只是“在罗马时……等”)。考虑到正则表达式的翻译可能涉及到对正则表达式的反复重新编译,因此我放弃了这一想法,原因是我认为上面的内容可能表现不佳。

更新#1:maketrans文档字符串有误导性和/或不正确

看着string.maketrans,我看到了:

maketrans doc

这表明 no 表示to参数是可选的。也没有说明https://stackoverflow.com/a/51481561/257924答案所指示的如何使用from字段的任何内容。

1 个答案:

答案 0 :(得分:0)

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