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

Python中如何不使用eval()根据字符串获取对应变量值?

问题

假设我有一组不同频率对应的背景测量数据:

import numpy as np

C_bg_100kHz = 100*np.random.random(1000)
C_bg_200kHz = 200*np.random.random(1000)

其中C_bg_100kHz为100kHz测量场景下的背景噪声,C_bg_200kHz为200kHz测量场景下的背景噪声。我需要编写一个函数,实现从测量数据数组中减去指定背景数据集的均值,函数支持通过参数指定要扣除的背景数据集。目前我使用eval()实现了该函数:

def subtract(array_y,freq):
    bg = eval('C_bg_' + freq)
    return array_y - np.ones(len(array_y))*np.mean(bg)

调用效果如下:

>>> subtract([50,50,50],'100kHz')
array([-0.36224706, -0.36224706, -0.36224706])

>>> subtract([50,50,50],'200kHz')
array([-47.95860607, -47.95860607, -47.95860607])

当前实现中,传入测量数据array_y,将'100kHz'作为freq参数传入即可扣除C_bg_100kHz数据集的均值,核心需求是让Python将字符串'C_bg_100kHz'解析为对应的数组变量C_bg_100kHz。但开发中应尽量避免使用eval(),现寻求不使用eval()的替代实现方案。

解答

最优方案:使用字典维护频率与背景数据的映射

这是最安全、可维护性最高的实现方式,从根源上避免动态解析变量名的需求:

import numpy as np

# 所有背景数据集统一存在字典中,key为频率标识,value为对应测量数组
bg_dataset = {
    "100kHz": 100 * np.random.random(1000),
    "200kHz": 200 * np.random.random(1000)
}

def subtract(array_y, freq):
    # 提前做参数校验,传入不支持的频率时抛出明确错误
    if freq not in bg_dataset:
        raise ValueError(f"无效频率参数,当前支持的频率为:{list(bg_dataset.keys())}")
    bg_mean = np.mean(bg_dataset[freq])
    # 直接利用numpy广播机制减标量,无需手动生成全1数组
    return np.asarray(array_y) - bg_mean

该方案的优势:

  • 无任意代码执行风险,完全规避eval()的安全问题
  • 支持的频率参数清晰可见,新增、删除、修改背景数据集只需要调整字典内容即可,维护成本极低
  • 参数错误时会返回明确的提示,不会出现动态解析变量时的模糊报错
  • 代码执行效率更高,写法更简洁

兼容旧代码方案:通过作用域字典查找变量

如果受限于历史代码结构,背景数据已经以独立变量的形式散落在全局作用域,无法重构为字典存储,可以直接通过Python内置的作用域字典查找变量,安全性远高于eval():

def subtract(array_y, freq):
    target_var = f"C_bg_{freq}"
    # globals()返回全局作用域的「变量名:变量值」映射字典
    if target_var not in globals():
        raise ValueError(f"未找到频率{freq}对应的背景数据集")
    bg = globals()[target_var]
    return np.asarray(array_y) - np.mean(bg)

注意:该方案仅适合临时兼容存量代码,新写代码请优先使用字典映射的方案,动态查找作用域变量依然存在维护性差、变量名冲突等问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 19:15:46