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

Python跨模块访问类变量报NameError: name 'b'未定义是何原因

跨模块访问类变量报NameError的原因与修复方案

问题复现

mod1.py(定义B类的模块)

class B:
    varb = 10
    def bkafunc(self):
        print("Mai B class ka func!")

触发报错的outmod1.py写法

from my_package.mod2 import B

class outMod:
    b = B()

    def func_out_mod(self):
        print(b.varb)

om = outMod()
om.func_out_mod()

运行抛出异常:NameError: name 'b' is not defined. Did you mean: 'B'?

可正常运行的临时写法

from my_package.mod2 import B

class outMod:
     def func_out_mod(self):
          print(B().varb)

om = outMod()
om.func_out_mod()

运行结果:正常打印varb的值10,但每次调用方法都会重复实例化B类,存在不必要的性能开销。


报错根本原因

这个报错和跨模块导入逻辑无关,核心是Python的作用域查找规则:

  • 类定义的代码块是独立作用域,你在类体里直接写b=B(),这个b是绑定在outMod类上的类属性,存在于outMod的类命名空间里,既不是模块级的全局变量,也不会自动进入类方法的局部作用域。
  • 你在func_out_mod方法里直接写b的时候,Python会按「方法局部变量→外层嵌套函数变量→模块全局变量→内置变量」的顺序查找名字,根本不会主动检索当前类的命名空间,自然找不到b,直接抛出NameError。
  • 临时可运行版本的逻辑本质是:B是导入到模块全局作用域的名字,方法里可以直接定位到B类,临时实例化之后取varb当然不会报错,但重复实例化的写法不符合资源复用的要求。

跨模块类变量的正确实现方式

根据业务场景选对应写法即可:

  • 如果希望只实例化一次B,所有outMod实例共用同一个B对象,就把b作为类属性,方法里通过类名或者实例引用访问:
from my_package.mod2 import B

class outMod:
    b = B()  # 类属性,所有outMod实例共享同个B实例
    def func_out_mod(self):
        # 写法1:直接通过类名访问
        print(outMod.b.varb)
        # 写法2:通过实例的类属性访问,不需要硬编码类名
        # print(self.__class__.b.varb)

om = outMod()
om.func_out_mod()
  • 如果希望每个outMod实例单独持有一个独立的B实例,就把b绑定为实例属性,在初始化方法里赋值:
from my_package.mod2 import B

class outMod:
    def __init__(self):
        self.b = B()  # 实例属性,每个outMod实例单独持有一个B实例
    def func_out_mod(self):
        print(self.b.varb)

om = outMod()
om.func_out_mod()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 12:24:23