Python 2.7中ast.literal_eval()对集合字面量的支持?

15 投票
2 回答
17116 浏览
提问于 2025-04-16 18:03

Python 2.7的新特性文档中提到,集合字面量的支持是从Python 3.1中移植过来的。不过,看起来这个支持并没有扩展到ast模块的literal_eval()函数,下面的例子就说明了这一点。

这是故意的、疏忽,还是其他原因呢?如果我想从字符串表示中创建一个字面量集合,有什么简单的方法?(我想在Python 3.1及以上版本中,这个是可以工作的,对吧?)

import ast
a_set = {1,2,3,4,5}
print(a_set) 
print(ast.literal_eval('{1,2,3,4,5}'))

输出显示错误信息:

set([1, 2, 3, 4, 5])
Traceback (most recent call last):
  File "...\setliterals.py", line 4, in <module>
    print ast.literal_eval('{1,2,3,4,5}')
  File "...\Python\lib\ast.py", line 80, in literal_eval
    return _convert(node_or_string)
  File "...\Python\lib\ast.py", line 79, in _convert
    raise ValueError('malformed string')
ValueError: malformed string

附言:我能想到的唯一解决办法就是使用eval()

2 个回答

0

来自错误报告:http://bugs.python.org/issue10091

Raymond Hettinger 说:

关于 ast.literal_eval 的文档:

‘提供的字符串或节点只能包含以下 Python 字面量结构:字符串、数字、元组、列表、字典、布尔值和 None。’

我认为我们可以从这份文档得出结论,这个问题不一定是个错误,因为集合字面量是从 Python 3.2 回溯到 3.1 和 2.7 的。对于使用 ast.literal 的 Python 2.7 用户来说,这 确实 是需要注意的事情。

3

我一直在用这个方法来转换pandas数据框中的列(df[col] = df[col].apply(to_set))。这个方法可能对那些看到这个问题的人有帮助。虽然它的速度可能没有那么快,但它避免了使用eval

def to_set(set_str):
    """
    Required to get around the lack of support for sets in ast.literal_eval. 
    It works by converting the string to a list and then to a set.

    Parameters
    ----------
    set_str : str
        A string representation of a set.

    Returns
    -------
    set

    Raises
    ------
    ValueError
        "malformed string" if the string does not start with '{' and and end 
        with '}'.

    """
    set_str = set_str.strip()
    if not (set_str.startswith('{') and set_str.endswith('}')):
        raise ValueError("malformed string")

    olds, news = ['{', '}'] , ['[',']']
    for old, new in izip(olds, news):        
        set_str = set_str.replace(old, new)

    return set(literal_eval(set_str))

撰写回答