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

Python函数递归调用时exec创建的全局变量丢失问题求助

问题原因
  • 你调用exec()时同时传入了全局作用域、本地作用域两个字典参数,Python默认会将exec内的赋值操作写入你传入的本地作用域(locals()),因此不会出现在全局变量查询结果中。
  • 你当前用字符串拼接构造exec语句的写法存在注入风险,如果用户输入带双引号、特殊转义符等内容,会直接导致代码报错甚至被插入执行恶意代码,非常不推荐。
解决办法

根据你的需求,提供三种可选实现方案:

方案1:调整exec参数实现全局赋值

如果一定要用exec实现动态赋值,只需要去掉第三个locals参数,exec内的赋值就会默认写入全局作用域,同时改用f-string+repr()处理输入内容,避免拼接出错:

class Item():
    def printVal(self,value):
        return value

    def func(self):
        userInput = input("Input string:")
        if userInput!="0":
            # 去掉locals参数,赋值默认写入全局作用域
            exec(f"a = self.printVal({repr(userInput)})", globals())
        else:
            return
        print(globals())
        self.func()

if __name__ == "__main__":
    item = Item()
    item.func()

方案2:直接操作全局字典(更安全,支持动态添加任意变量)

如果后续要按需添加任意名称的变量,直接修改globals()字典比用exec更安全可控,完全规避动态代码执行的风险:

if userInput!="0":
    var_name = "a" # 可替换为任意你需要的变量名
    var_value = self.printVal(userInput)
    globals()[var_name] = var_value

只要修改var_name的值,就可以动态添加任意名称的全局变量,符合你后续拓展的需求。

方案3:用实例属性存储(更符合面向对象规范)

如果你只需要在Item类的实例递归调用时读取变量,不需要真的全局可用,把变量存在实例属性里是更合理的选择,不会污染全局作用域:

if userInput!="0":
    var_name = "a"
    var_value = self.printVal(userInput)
    # 给实例动态添加属性
    setattr(self, var_name, var_value)
# 后续递归调用时直接读取即可,比如 print(self.a)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 15:27:01