从字符串“正确地"创建一个lambda函数 [英] create a lambda function from a string **properly**

查看:76
本文介绍了从字符串“正确地"创建一个lambda函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出一个字符串,例如

"2*(i+j) <= 100"

我想生成相应的lambda函数,

I want to generate the corresponding lambda function,

fn = lambda i,j: 2*(i+j) <= 100

  • 我可以用eval做到这一点,但是我正在寻找一种不太邪恶的方法.

    • I can do this with eval, but I am seeking a less evil method.

      我找到了

      import ast
      f = ast.Lambda('i,j', '2*(i+j) <= 100')
      

      但是我还没有弄清楚如何执行结果!

      but I haven't figure out how to execute the result!

      理想情况下,我也想自动提取参数列表('i','j')-现在,我只是使用re.findall('\ w +'),但我会喜欢能够正确使用cos之类的现有功能,而不是将它们隐藏为关键字".

      Ideally, I would like to automatically pull out the parameter list ('i','j') as well - right now, I am just using re.findall('\w+'), but I would love to be able to properly use existing functions like cos instead of shadowing them as 'keywords'.

      我正在查看是否存在并尝试找出如何最好地将set-builder表示法解析为lambda以便馈送给约束求解器的Python库用于处理复杂的数学集(使用数学set-builder表示法构建).

      I was looking at Is there a Python library for handling complicated mathematical sets (constructed using mathematical set-builder notation)? and trying to figure out how best to parse the set-builder notation into the lambdas to feed to the constraint-solver.

      我基本上希望ast.literal_eval也可以识别变量.

      I'm basically wishing for ast.literal_eval which would also recognize variables.

      理想情况下,考虑到i >= 20,我想找回((lambda x: x >= 20), ['i']),然后我可以直接将其喂入constraint.

      Ideally, given i >= 20 I would like to get back ((lambda x: x >= 20), ['i']) which I could then feed directly to constraint.

      推荐答案

      如果您的输入来自受信任的来源,则 eval()是最简单,最清晰的,也是最可靠的方法.

      If your input is from a trusted source, the eval() is the easiest, clearest, and most reliable way to go.

      如果您输入的内容不受信任,则需要对其进行清理.

      If your input is untrusted, then it needs to be sanitized.

      一种合理的方法是使用正则表达式.确保字符串中没有函数调用,属性查找或双下划线.

      One reasonable approach is the use of a regex. Make sure there are no function calls, attribute lookups, or double underscores in the string.

      或者,一种更复杂的方法是遍历AST解析树以确定是否有任何令人反感的呼叫.

      Alternatively, a more sophisticated approach is to walk the AST parse tree to determine whether there are any objectionable calls.

      第三种方法是遍历AST解析树并直接执行它.这样一来,您就可以完全控制收到电话的内容. ast.literal_eval函数采用这种方法.也许您从其源代码开始,并对要支持的任何操作进行一些扩展:

      A third approach is to walk the AST parse tree and execute it directly. That puts you in complete control over what gets calls. The ast.literal_eval function takes this approach. Perhaps you start with its source and do some buildouts for any operations you want to support:

      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)
      

      这篇关于从字符串“正确地"创建一个lambda函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆