You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取eval表达式使用的变量?mock方案遇比较符报错如何解决?

解决方案

方案1:重写MagicMock支持比较运算符

继承MagicMock实现所有比较运算符的魔法方法,返回实例自身即可避免报错,同时不影响原有的__getitem__调用记录逻辑:

import mock

class MockDict(mock.MagicMock):
    # 实现所有比较运算符,返回自身避免类型错误
    def __lt__(self, other):
        return self
    def __gt__(self, other):
        return self
    def __le__(self, other):
        return self
    def __ge__(self, other):
        return self
    def __eq__(self, other):
        return self
    def __ne__(self, other):
        return self

def get_eval_vars(expr):
    mock_var = MockDict()
    eval(expr, {"__builtins__": {}}, mock_var)
    # 去重后返回,避免同一个变量被多次调用返回重复结果
    return list({args[0][0] for args in mock_var.__getitem__.call_args_list})

# 测试用例
print(get_eval_vars("a+b+10")) # 输出 ['a', 'b']
print(get_eval_vars("a<10"))   # 输出 ['a']

该方案适配原有实现逻辑,改动量小,缺点是如果遇到MagicMock未实现的其他运算符(如位运算、成员运算)仍可能触发报错。

方案2:基于AST语法树解析(更稳定,无需执行表达式)

该方案不需要实际执行eval表达式,仅通过解析Python抽象语法树提取变量名,完全不存在运算符支持问题,也规避了执行表达式的潜在安全风险,是更推荐的实现:

import ast

def get_eval_vars(expr):
    variables = set()
    # 遍历语法树所有节点
    for node in ast.walk(ast.parse(expr, mode='eval')):
        # 匹配变量加载节点,排除函数调用、赋值等其他类型节点
        if isinstance(node, ast.Name) and isinstance(node.ctx, ast.Load):
            variables.add(node.id)
    return list(variables)

# 测试用例
print(get_eval_vars("a+b+10")) # 输出 ['a', 'b']
print(get_eval_vars("a<10"))   # 输出 ['a']
print(get_eval_vars("(a * b) >= c and d in [1,2,3]")) # 输出 ['a', 'b', 'c', 'd']

内容的提问来源于stack exchange,提问作者Iñigo Moreno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 09:27:04