Python如何动态导入类并实现跨文件引用动态生成的多继承类
问题根因
你的代码无法生效的核心原因有两点:
- 模块顶层代码执行时机早于
main()调用:Python加载模块时会直接执行所有顶层代码,此时你还没修改SigClass.sig、也没运行main()生成TempClass,如果此时在其他文件或者MainClass.py顶层引用MainClass,拿到的都是初始定义的空类。 - 导入的是引用快照:如果你在
main()运行前就执行了from MainClass import MainClass,这个导入会把当时MainClass变量指向的空类绑定到当前文件的命名空间,后续就算MainClass模块的MainClass变量被修改为TempClass,你当前命名空间里的旧引用也不会自动更新。
最小改动修复现有代码
如果要保留你现有的实现逻辑,只需要调整导入方式和冗余代码即可:
- 所有用到
MainClass的地方,不要提前用from MainClass import MainClass绑定到本地命名空间,直接导入MainClass模块,通过模块访问最新的MainClass属性。修改后的main.py示例:
import MainClass MainClass.SigClass.sig = "MyClassC" MainClass.main() MainClass.MainClass.function_a() print(MainClass.MainClass.property)
- 去掉冗余继承:
MyClassC已经继承了MyClassA,TempClass不需要重复继承,避免MRO混乱,修改MainClass.py的main函数逻辑:
def main(): module_name = SigClass.sig class_name = SigClass.sig module_object = importlib.import_module(module_name) module_class_object = getattr(module_object, class_name) class TempClass(module_class_object): pass global MainClass MainClass = TempClass
- 如果你需要在
MainClass.py的顶层使用MainClass,不要直接写调用逻辑,把相关逻辑封装到函数里,等main()运行完成后再调用。
更推荐的实现方案
你当前动态修改模块全局变量的实现很容易因为导入顺序出问题,推荐用工厂模式实现,逻辑更清晰也更稳定:
- 删掉
MainClass.py顶层的空MainClass定义,把类生成逻辑封装为工厂函数,还可以加缓存避免重复生成类:
from time import time from SigClass import SigClass import importlib _main_class_cache = None class MyClassA: sig = '1' property = 'A' @classmethod def function_a(cls): cls.property = 'A' def get_main_class(): global _main_class_cache if _main_class_cache is not None: return _main_class_cache module_name = SigClass.sig class_name = SigClass.sig module_object = importlib.import_module(module_name) module_class_object = getattr(module_object, class_name) class MainClass(module_class_object): pass _main_class_cache = MainClass return MainClass
- 所有需要用到
MainClass的地方,都调用get_main_class()获取即可,修改后的main.py示例:
import MainClass MainClass.SigClass.sig = "MyClassC" MainCls = MainClass.get_main_class() MainCls.function_a() print(MainCls.property)
这个方案完全规避了导入顺序和全局变量修改的问题,所有地方拿到的都是符合当前sig配置的类。
内容的提问来源于stack exchange,提问作者jaried
相关产品推荐
相关产品推荐

