首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >循环和列表理解在使用exec创建变量时无法找到它们。

循环和列表理解在使用exec创建变量时无法找到它们。
EN

Stack Overflow用户
提问于 2022-06-22 13:03:32
回答 2查看 38关注 0票数 -1

在我的(简化)脚本中,我有以下内容:

代码语言:javascript
复制
def predict(new_data):
 .
 .
 .
 model_list = fetch_needed_models() # ["f1","f2","f3"]

 for m in model_list:
      with open(f"./{m}.pkl","rb") as file:
          exec(f"{m}=pickle.load(file)")

 print(dir()) # [...,'f1','f2','f3',...]

 # Try with list-comprehension
 f1_pred = [f1.predict(x) for x in new_data] # NameError: name 'f1' does not exists
 
 # Try with loop
 f1_pred = []
 for x in new_data:
    f1_pred.append(f1.predict(x)) # NameError: name 'f1' does not exists

如果我在函数之外运行这些行,即只一个接一个地运行这些行(在VScode中,交互式窗口中),它可以很好地工作,但是当我像python main.py一样运行这个函数时,会得到一个NameError: name 'f1' is not defined错误。我认为可能exec没有正确执行,但是在exec命令之后的print(dir())显示,变量确实存在。

有人知道为什么吗?

编辑

一个简单的测试,比如

代码语言:javascript
复制
def test():
    exec("f= []")
    f.append(2)
    print(f)

if __name__=="__main__":
 test()
代码语言:javascript
复制
> python test.py
>      "NameError: name "f" is not defined

也失败了

EN

回答 2

Stack Overflow用户

发布于 2022-06-22 14:09:36

如果您确实想使用exec (您不应该使用,并且应该重构代码以避免它),那么您必须传递要在其中执行代码的环境。使用简化的示例,您可以这样做:

代码语言:javascript
复制
def test():
    exec("f= []", globals())
    f.append(2)
    print(f)

if __name__=="__main__":
 test()  # [2]
票数 1
EN

Stack Overflow用户

发布于 2022-06-22 14:10:17

局部变量是编译时特性;即使使用exec,也不能在运行时将真正的局部变量添加到函数中。编译时,计算局部变量的固定大小数组的大小,并在该数组中为每个名称分配一个索引;数组不能展开,无法识别的名称没有映射。您可以使用locals() (它复制真正的局部变量,然后是一个可以变异的dict )来伪造它,但是不要。

只需使用由您所关心的名称组成的dict键:

代码语言:javascript
复制
def predict(new_data):
 .
 .
 .
 model_list = fetch_needed_models() # ["f1","f2","f3"]

 models = {}
 for m in model_list:
      with open(f"./{m}.pkl","rb") as file:
          models[m] = pickle.load(file)

 # Try with list-comprehension
 f1_pred = [models['f1'].predict(x) for x in new_data]
 
 # Try with loop
 f1_pred = []
 for x in new_data:
    f1_pred.append(models['f1'].predict(x))

如果您知道f1总是存在于其中,您可以直接提取它,但是这种方法违背了动态指定模型的目的:

代码语言:javascript
复制
def predict(new_data):
 .
 .
 .
 model_list = fetch_needed_models() # ["f1","f2","f3"]

 models = {}
 for m in model_list:
      with open(f"./{m}.pkl","rb") as file:
          models[m] = pickle.load(file)

 # We're sure f1 will be there, so we can make it a local manually    
 f1 = models['f1']

 # Try with list-comprehension
 f1_pred = [f1.predict(x) for x in new_data]
 
 # Try with loop
 f1_pred = []
 for x in new_data:
    f1_pred.append(f1.predict(x))
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72716045

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档