在类方法中使用exec赋值变量触发NameError问题求助
问题描述
在Jupyter Notebook中运行以下Python类方法代码:
def method(self, data, **kwargs): # parse kwargs thetas to namespace for theta, val in kwargs.items(): print(theta,val) exec(f"{theta}={val}") print(kwargs) print(theta1,theta2) # ... return
执行后输出如下内容并报错:
theta1 0.0001 theta2 0.0001 {'theta1': 0.0001, 'theta2': 0.0001} NameError: name 'theta1' is not defined
原本以为exec会定义theta1、theta2等变量,尝试过添加globals()和locals()参数也无效,求原因及解决办法。
原因分析与解决方案
核心原因
Python函数(包括类方法)的本地命名空间是编译时静态确定的,exec属于动态执行代码,无法被Python的静态变量分析机制捕获,因此即使exec执行了变量赋值,函数后续也无法识别这些动态创建的变量。另外,函数内部的locals()字典是只读的,直接修改它不会同步回实际的本地命名空间,所以添加locals()参数也没用。
解决办法
不推荐用exec动态创建变量,既不安全也不符合Python编码规范,推荐以下两种更合理的方式:
用字典统一存储参数
把kwargs里的参数存到一个字典中,后续通过字典键访问:def method(self, data, **kwargs): thetas = kwargs.copy() print(thetas) print(thetas['theta1'], thetas['theta2']) # ... return绑定为实例属性
如果这些参数属于类实例的属性,可以直接通过setattr绑定到self:def method(self, data, **kwargs): for theta, val in kwargs.items(): setattr(self, theta, val) print(kwargs) print(self.theta1, self.theta2) # ... return若必须用exec(不推荐)
可以通过globals()操作全局命名空间,但会污染全局变量,仅适合临时测试:def method(self, data, **kwargs): for theta, val in kwargs.items(): exec(f"{theta}={val}", globals()) print(kwargs) print(theta1, theta2) # ... return
内容的提问来源于stack exchange,提问作者user19976975
相关产品推荐
相关产品推荐

