【问题标题】:How to use eval() function with a list of variables?如何将 eval() 函数与变量列表一起使用?
【发布时间】:2019-01-28 11:26:36
【问题描述】:

我有一个字符串形式的函数列表:

["y + x + 3", "x**2 + y**2 - 17"]  # 2 functions in list

我有一个Sympy Symbol 对象(基本上是变量)列表,其中.name 属性与函数字符串中的变量名称对应:

[Symbol(x), Symbol(y)]
# list element 0's .name attribute is "x" 

我发现 Python 有一个名为 eval() 的简洁函数,它可以计算字符串,例如:

x = 1
eval("x + 3") # Result should be 4

基本上这就是我想要对函数字符串执行的操作。然而,由于这是一个动态实现,我没有在我的程序中eval() 上方的行上定义变量,而是在一个列表中。例如,在上面的例子中,x 被定义为 1,那么eval() 函数就可以使用它。

但是我的变量在一个列表中,没有定义为我的函数范围内的变量。 如何使用eval() 函数并利用我的变量列表?

【问题讨论】:

    标签: python eval


    【解决方案1】:

    eval 将局部变量作为第三个参数(reference), 所以你可以这样做:

    from sympy import Symbol
    zs = [Symbol('x'), Symbol('y')]
    eval('x+y', None, dict([z.name, z] for z in zs))
    

    但是,也许您应该使用 parse_expr,它是 SymPy 的一部分。

    from sympy import Symbol
    from sympy.parsing.sympy_parser import parse_expr
    zs = [Symbol('x'), Symbol('y')]
    parse_expr('x+y', local_dict=dict([z.name, z] for z in zs))
    

    【讨论】:

    • 我来看看 parse_expr 方法。现在,我根据您的建议与 eval() 一起工作。但也许另一个更好。
    【解决方案2】:

    这个怎么样,你可以在你的符号类中包装以下替换和评估代码(通过继承)。

    import ast
    
    x = 5
    y = 6
    
    function_str = "y + x + 3"
    function_str = function_str.replace('x', '{x}')
    function_str = function_str.replace('y', '{y}')
    
    print(ast.literal_eval(function_str.format(x=x, y=y)))
    # 14
    

    永远记住,使用 eval 是“EVAL”,因为你不应该相信传入的字符串,listeral_eval 更安全。

    【讨论】:

      【解决方案3】:

      您可以按照以下方式做一些事情:

      import math
      
      symbols = {'sqrt': math.sqrt, 'x': 5, 'y': 6}
      
      func_strings = ["y + x + 3", "x**2 + y**2 - 17", "sqrt(1764)"]
      
      for expression in func_strings:
          result = eval(expression, {'__builtins__': None}, symbols)
          print('{} -> {}'.format(expression, result))
      

      输出:

      y + x + 3 -> 14
      x**2 + y**2 - 17 -> 44
      sqrt(1764) -> 42.0
      

      【讨论】:

        【解决方案4】:

        查看eval (expression[, globals[, locals]])的完整定义

        您可以将globals/locals 替换为eval

        例如

        eval("x + 3", {"x":1}) # Result should be 4
        

        如何使用 eval() 函数并利用我的变量列表?

        你有 2 个命名空间,你可以用它们做任何你想做的事情。

        【讨论】:

          【解决方案5】:

          在我看来,最好的方法是将所有变量添加到locals。然后您可以在eval 中按名称引用它们。示例:

          symbols = [Symbol(x), Symbol(y)]
          locals().update({symbol.name:symbol for symbol in symbols})
          
          eval("x+y") # Should return the value of x+y
          

          【讨论】:

          • documentation 明确指出字典 locals() 返回不应更新,因为这样做不可靠。
          猜你喜欢
          • 1970-01-01
          • 2018-11-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-09-10
          • 1970-01-01
          • 2011-11-26
          相关资源
          最近更新 更多