如何跨模块使用全局类对象引用?附报错及代码示例
问题分析与解决方案
错误原因
你在third.py里写self.a.config.c时出错,核心原因是:config是一个独立模块,并不是myfirst.b类实例的属性。b类的__init__只是修改了config模块里的c变量,但并没有把config绑定到自身实例上,所以访问self.a.config自然会报属性不存在的错误。
跨模块使用类对象引用的实用方法
方法1:直接导入共享模块访问
既然config是专门用来存储全局对象的模块,直接在需要的地方导入config模块即可,完全不需要通过b实例中转:
修改third.py代码:
import myfirst import config class s: def __init__(self): self.a = myfirst.b() print(config.c) # 直接访问config模块的c变量,就能拿到second.c的实例 s()
执行后会正常输出hy,并打印出second.c的实例对象。
方法2:给b类添加实例属性存储引用
如果非要通过b实例访问,可以在b的初始化方法里,把config模块或者config.c的引用绑定到实例属性上:
修改myfirst.py:
import second import config class b: def __init__(self): config.c = second.c() self.config = config # 把config模块绑定到b实例的属性上 # 也可以直接存c的引用:self.c_instance = config.c
然后third.py里就能这样写:
import myfirst import config class s: def __init__(self): self.a = myfirst.b() print(self.a.config.c) # 现在能正常访问到了 # 如果是存self.c_instance,就写print(self.a.c_instance) s()
方法3:单例模式(适合全局唯一实例场景)
如果second.c的实例只需要一个全局唯一的,可以把它做成单例,这样在任何模块里导入直接使用即可,不需要通过config中转:
修改second.py:
class c: _instance = None def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance = super().__new__(cls, *args, **kwargs) return cls._instance def __init__(self): # 避免重复执行初始化逻辑,加个判断 if not hasattr(self, '_initialized'): print("hy") self._initialized = True
之后在其他模块里使用时,无论调用多少次second.c(),拿到的都是同一个实例:
比如myfirst.py可以简化为:
import second class b: def __init__(self): self.c_instance = second.c() # 每次获取的都是同一个实例
third.py里:
import myfirst import second class s: def __init__(self): self.a = myfirst.b() print(self.a.c_instance) print(second.c()) # 和上面的是同一个实例 s()
方法4:依赖注入(低耦合的灵活方式)
如果不想依赖全局变量,可以在创建b实例时直接传入c的实例,或者让b从外部接收c的实例,这样模块间的耦合度更低:
修改myfirst.py:
import second class b: def __init__(self, c_instance=None): # 如果外部没传实例,就自己创建;否则用传入的 self.c_instance = c_instance or second.c()
然后third.py里:
import myfirst import second class s: def __init__(self): # 可以自己创建c实例传入,或者从其他模块获取后传入 c_obj = second.c() self.a = myfirst.b(c_instance=c_obj) print(self.a.c_instance) s()
内容的提问来源于stack exchange,提问作者Sritam Nayak
相关产品推荐
相关产品推荐

