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

如何在不修改self.data的情况下实现字典键的代数表达式求值?

解决eval修改原字典的问题

问题原因

当你将self.data直接作为eval()的globals参数传入时,Python会自动向这个字典中添加__builtins__键,这就是原字典被修改的根源。


方案1:用临时字典避免修改原数据

不需要深拷贝,只需构造一个包含self.data内容的新字典,传给eval()即可。原字典self.data不会被改动,因为eval()只会修改传入的临时字典。

代码实现:

import ast

class A():
    def __init__(self, data=None):
        self.data = {} if data is None else data

    def __getitem__(self, src:str):
        parsed_expr = ast.parse(src, mode='eval')
        compiled_expr = compile(parsed_expr, '', 'eval')
        # 构造临时全局字典,包含原数据和内置模块
        temp_globals = {**self.data, '__builtins__': __builtins__}
        item = eval(compiled_expr, temp_globals)
        return item

obj = A({'open':1,'close':1})
print(obj['close + open']) # 输出2
print(obj.data) # 输出{'open':1,'close':1},无__builtins__

方案2:限制内置函数提升安全性(可选)

如果担心表达式中调用危险内置函数,可以只提供运算所需的最小内置集合,进一步降低风险:

import ast
import math

class A():
    def __init__(self, data=None):
        self.data = {} if data is None else data

    def __getitem__(self, src:str):
        parsed_expr = ast.parse(src, mode='eval')
        compiled_expr = compile(parsed_expr, '', 'eval')
        # 只提供必要的内置函数和数学工具
        safe_globals = {
            **self.data,
            '__builtins__': {
                'abs': abs,
                'pow': pow,
                'sum': sum,
                **math.__dict__
            }
        }
        item = eval(compiled_expr, safe_globals)
        return item

obj = A({'open':1,'close':1})
print(obj['(open+close)/2']) # 输出1.0
print(obj.data) # 原字典未被修改

内容的提问来源于stack exchange,提问作者apt45

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 22:15:28