将元组字符串转换为字符串元组

时间:2016-02-02 12:53:47

标签: python

我的输入是:

input = ['(var1, )', '(var2,var3)']

预期输出为:

output = [('var1', ), ('var2','var3')]

迭代输入并在元组字符串上使用eval / literal_eval是不可能的:

>>> eval('(var1, )')
>>> NameError: name 'var1' is not defined

如何将'(var1, )'之类的项目转换为内部对象被视为字符串而不是变量的元组?

是否有比编写解析器或使用正则表达式更简单的方法?

3 个答案:

答案 0 :(得分:12)

对于每次出现的变量,eval在符号表中搜索变量的名称。可以提供自定义映射,该映射将返回每个缺失键的键名称:

class FakeNamespace(dict):
    def __missing__(self, key):
        return key

示例:

In [38]: eval('(var1,)', FakeNamespace())
Out[38]: ('var1',)

In [39]: eval('(var2, var3)', FakeNamespace())
Out[39]: ('var2', 'var3')

注意: eval将当前全局变量复制到提交的globals字典,如果它没有__builtins__。这意味着表达式可以访问内置函数,异常和常量,以及命名空间中的变量。您可以尝试通过传递FakeNamespace(__builtins__=<None or some other value>)而非FakeNamespace()来解决此问题,但不会使eval 100%安全(Python eval: is it still dangerous if I disable builtins and attribute access?

答案 1 :(得分:5)

试试这个:

tuples = [tuple(filter(None, t.strip('()').strip().split(','))) for t in input]

例如:

In [16]: tuples = [tuple(filter(None, t.strip('()').strip().split(','))) for t in input]

In [17]: tuples
Out[17]: [('var1',), ('var2', 'var3')]

我们正在遍历我们的元组字符串列表,并为每个字符串删除(),然后将{1}}将字符串拆分为列表,然后将列表转换回一个元组。我们使用filter()删除空元素。

答案 2 :(得分:4)

我喜欢vaultah的解决方案。如果ast.literal_eval不是选项,那么另一个reeval

>>> import re
>>> from ast import literal_eval
>>> [literal_eval(re.sub('(?<=\(|,)(\w+)(?=\)|,)', r'"\1"', x)) for x in input]
[('var1',), ('var2', 'var3')]