给出一个字符串,
"2*(i+j) <= 100"
我想生成相应的lambda函数,
fn = lambda i,j: 2*(i+j) <= 100
我可以做到这一点eval
,但是我正在寻找一个不太坏的方法。
我已经找到
import ast f = ast.Lambda('i,j', '2*(i+j) <= 100')
但我还没有想出如何执行的结果!
理想情况下,我想自动拉出参数列表(“我”,“J”),以及 - 现在,我只是用re.findall(“\ w +”),但我很想能够正确利用现有的功能,如cos
,而不是阴影他们为“关键字”。
我一直在寻找是否有一个Python库来处理复杂的数学组(使用数学集合建构式符号构建的)? 并试图找出如何最好地解析集合建构式符号到lambda表达式喂到约束解算器。
基本上,我希望为ast.literal_eval这也将认识到的变量。
理想情况下,给定的i >= 20
我想取回((lambda x: x >= 20), ['i'])
我可以然后直接进料到constraint
。
如果输入是来自可信来源中,eval()是最简单的,最明显的,并且要最可靠的方式。
如果你的输入是不可信的 ,那么就需要进行消毒 。
一个可行的办法是使用正则表达式。 确保没有函数调用,属性查询,或双下划线的的字符串中。
另外,一个更复杂的方法是走AST解析树,以确定是否有任何反感的电话。
第三种方法是走AST解析树并直接执行它。 这使您可以完全控制什么获取电话。 该ast.literal_eval功能采取了这种办法。 也许你开始使用它的源和做要支持任何操作一些网络建设:
def literal_eval(node_or_string):
"""
Safely evaluate an expression node or a string containing a Python
expression. The string or node provided may only consist of the following
Python literal structures: strings, numbers, tuples, lists, dicts, booleans,
and None.
"""
_safe_names = {'None': None, 'True': True, 'False': False}
if isinstance(node_or_string, basestring):
node_or_string = parse(node_or_string, mode='eval')
if isinstance(node_or_string, Expression):
node_or_string = node_or_string.body
def _convert(node):
if isinstance(node, Str):
return node.s
elif isinstance(node, Num):
return node.n
elif isinstance(node, Tuple):
return tuple(map(_convert, node.elts))
elif isinstance(node, List):
return list(map(_convert, node.elts))
elif isinstance(node, Dict):
return dict((_convert(k), _convert(v)) for k, v
in zip(node.keys, node.values))
elif isinstance(node, Name):
if node.id in _safe_names:
return _safe_names[node.id]
elif isinstance(node, BinOp) and \
isinstance(node.op, (Add, Sub)) and \
isinstance(node.right, Num) and \
isinstance(node.right.n, complex) and \
isinstance(node.left, Num) and \
isinstance(node.left.n, (int, long, float)):
left = node.left.n
right = node.right.n
if isinstance(node.op, Add):
return left + right
else:
return left - right
raise ValueError('malformed string')
return _convert(node_or_string)
您正在寻找一个替代eval
,但为什么呢? 你接受任意代码反正执行它,那么为什么不使用eval
? 避免的唯一原因eval
是因为它是危险的,但是你最终可以创建拉姆达将是多么危险。
另外,要记住, 你真的不能使之安全在CPython的做到这一点