我想过滤变量(即删除无效内容),以便ast.literal_eval
可以解析其字符串表示形式。所以基本上是一个filter_literal
函数,可以保证任何obj
的以下断言:
safe_obj = filter_literal(obj)
assert ast.literal_eval(repr(safe_obj))==safe_obj
我提出了以下功能,但我感兴趣的是有更好的方法,否则,如果我做错了什么:
_literal_types = set([type(None),bool,int,float,long,complex])
def filter_literal(obj, default=None):
""" return given `obj` with only "literal" types
The output can be safely converted to string and evaluated using
`ast.literal_eval`::
import ast
safe_obj = filter_literal(obj)
assert ast.literal_eval(repr(obj))==safe_obj
literal types are strings, number, tuples, lists, dicts, booleans and None
non-literal content are replaced by `default`
"""
obj_type = type(obj)
if obj_type in _literal_types:
return obj
elif isinstance(obj,dict):
return dict((k,filter_literal(v,default=default)) for k,v in obj.iteritems())
elif isinstance(obj,list):
return [filter_literal(v,default=default) for v in obj]
elif isinstance(obj,tuple):
return tuple([filter_literal(v,default=default) for v in obj])
else:
return default
答案 0 :(得分:1)
一个明显的错误是你没有处理不是字典键的字符串:
>>> test = {"bar": [1, True, None, "foo"]}
>>> filter_literal(test)
{'bar': [1, True, None, None]}
你应该添加:
if isinstance(obj, basestring):
return obj
在决定你是否做错了什么的时候,测试你的功能:
for test in [{"bar": [1, True, None, "foo"]}, ...]:
assert ast.literal_eval(repr(filter_literal(test))) == test
定义一些测试并在进行更改时运行它。 另请注意,您可以简化递归调用,例如:
filter_literal(v, default)
我会在函数中移动_literal_types
:
def filter_literal(obj, default=None):
"""docstring."""
_literal_types = set([type(None), bool, int, float, long, complex])
...