如何在python eval表达式中检测变量

Hol*_*lle 0 python

假设我得到一个字符串到eval

temperature*x
Run Code Online (Sandbox Code Playgroud)

我有两组变量-简单的一组:

easy_ns = {'x':3, 'y':4}
Run Code Online (Sandbox Code Playgroud)

还有一个更难的:

harder = ['temperature', 'sumofall']
Run Code Online (Sandbox Code Playgroud)

每种计算都需要花费大量时间,除非它们是用户提供的表达式的一部分,否则我不想计算它们

例如,除非我知道这是必需的,否则我不想开始检测“温度”

我的命名空间中可能有一些“便宜”的变量,但我想尽可能推迟其他一些变量

如何在评估之前从评估字符串中获取变量列表

我知道我可以尝试:eval()除外:我会得到:

NameError: name 'temperature' is not defined
Run Code Online (Sandbox Code Playgroud)

有没有一种提取确切变量名称的pythonic方法?

有没有一种好的方法可以为延迟评估构建名称空间?

就像是

namespace = {'x':3, 'y':4, 'temperature':lazy_temperature_function}
Run Code Online (Sandbox Code Playgroud)

这样,只有当我的表情被评估

res=eval('temperature*x')
Run Code Online (Sandbox Code Playgroud)

我的懒惰温度函数叫做

而且当然的-我绝对必须使用“EVAL” -这就是为什么我已经发布了这些问题

场景是我得到一个包含键和值集的输入文件,然后用户可以提供他要我根据这些值和一些我不希望计算的生成变量的组合来计算的表达式,除非用户将它们包括在内在他/她的表情中

And*_*zlo 6

如果确实需要,可以使用该ast模块解析代码。该ast.parse助手会给你的代码的AST树表示:

import ast
code = "temperature*x"
st = ast.parse(code)
for node in ast.walk(st):
    if type(node) is ast.Name:
        print(node.id)
Run Code Online (Sandbox Code Playgroud)

这将打印:

temperature
x
Run Code Online (Sandbox Code Playgroud)

因此,这只会提取变量名,就像您说的那样。这似乎是第一步,但我不确定您要尝试做什么,也许使用其他方法更好。

编辑:如果我正确地理解了您的问题,那么您只希望某些值出现在表达式中时才进行计算?我尝试过这样的事情:

>>> import ast
>>> code = "temperature*x"
>>> x = 5
>>> def lazy_temperature():
    return 78
... 
>>> names = [node.id for node in ast.walk(ast.parse(code))
             if type(node) is ast.Name]
>>> ns = {name: (globals()['lazy_%s' % name])()
                 if ('lazy_%s' % name) in globals()
                 else globals()[name] 
          for name in names}
>>> ns
{'x': 5, 'temperature': 78}
>>> eval(code, ns)
390
Run Code Online (Sandbox Code Playgroud)

除非有一个名为的函数,否则此代码段会将值加载到当前范围之外lazy_<name>。如果<name>零件出现在表达式中,则将调用此函数。