Python 2.7中ast.literal_eval()对集合字面量的支持?
在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))