[英]filter a variable such that its repr can be parsed by literal_eval
I would like to filter a variable (ie remove invalid content) in order for its string representation to be parsable by ast.literal_eval
. 我想过滤一个变量(即删除无效内容),以便ast.literal_eval
可以解析其字符串表示ast.literal_eval
。 So basically a filter_literal
function that guaranties the below assertion for any obj
: 因此,基本上, filter_literal
函数可为任何obj
保证以下断言:
safe_obj = filter_literal(obj)
assert ast.literal_eval(repr(safe_obj))==safe_obj
I came up with the following function but I am interested if there is a better approach or, otherwise, if I did anything wrong: 我想出了以下功能,但是我对是否有更好的方法感兴趣,或者是否做错了任何事情,我很感兴趣:
_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
One obvious error is that you aren't dealing with strings that aren't dictionary keys: 一个明显的错误是您没有处理不是字典键的字符串:
>>> test = {"bar": [1, True, None, "foo"]}
>>> filter_literal(test)
{'bar': [1, True, None, None]}
You should add: 您应该添加:
if isinstance(obj, basestring):
return obj
In terms of deciding whether you've done anything wrong, test your function : 在确定您做错了什么方面, 测试一下您的功能 :
for test in [{"bar": [1, True, None, "foo"]}, ...]:
assert ast.literal_eval(repr(filter_literal(test))) == test
Define some tests and run this whenever you make changes. 定义一些测试,并在进行更改时运行它。 Also, note that you can simplify your recursive calls, eg: 另外,请注意,您可以简化递归调用,例如:
filter_literal(v, default)
and I would move _literal_types
inside the function: 我将在函数内部移动_literal_types
:
def filter_literal(obj, default=None):
"""docstring."""
_literal_types = set([type(None), bool, int, float, long, complex])
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.