Python调用导入函数时因依赖在当前环境报NameError问题咨询
问题根因
Python的函数作用域在定义阶段就已经确定,函数访问全局变量时,只会查找自身定义所在模块的全局命名空间,不会使用调用方所在模块的命名空间:
- 本地d.py可正常运行的原因是:
buzz定义在d.py模块中,它的全局作用域就是d.py的命名空间,调用buzz()时能成功找到同模块下定义的Foobar类 - b.py和c.py组合运行失败的原因是:
buzz定义在b.py模块中,它找全局变量时只会查找b.py的命名空间,b.py中没有定义Foobar,哪怕调用方c.py中定义了Foobar,buzz也无法访问,因此抛出NameError
可行实现方案
以下几种方案都可以满足动态调整buzz行为的需求:
方案1:将Foobar类作为参数传入(最推荐,耦合度最低)
修改b.py的buzz定义,显式接收类参数:
# b.py def buzz(foobar_cls): foobar = foobar_cls() # 其余业务逻辑
c.py调用时传入对应类即可:
# c.py from b import buzz class Foobar: pass buzz(Foobar)
方案2:给b模块注入依赖
无需修改b.py原有代码,在c.py中导入整个b模块,主动给b模块的命名空间赋值Foobar即可:
# c.py import b class Foobar: pass # 给b模块的全局命名空间注入Foobar b.Foobar = Foobar b.buzz()
方案3:闭包生成定制化的buzz实例
如果需要批量生成绑定不同Foobar变体的buzz函数,可以用闭包实现:
# b.py def build_buzz(foobar_cls): def buzz(): foobar = foobar_cls() # 其余业务逻辑 return buzz
c.py使用时:
# c.py from b import build_buzz class Foobar: pass buzz = build_buzz(Foobar) buzz()
内容的提问来源于stack exchange,提问作者Aristide
相关产品推荐
相关产品推荐

