为何从Python模块导入类时会执行模块内的类对象列表实例化代码?
问题原因
Python 的模块导入机制设计如此:无论你使用 import module 还是 from module import xxx 语法导入模块内容,都会完整执行目标模块的所有顶层代码,类定义、顶层变量赋值都属于顶层代码,因此你写在模块最外层的 LIST_OF_A = [ A(2,3), B(4,5) ] 会在导入时自动执行,完成列表和内部类实例的创建。
注:你给出的示例代码本身存在几处语法错误,修复后才能正常运行:
- 数据类的导入应为
import dataclasses,装饰器为@dataclasses.dataclass big_method里访问属性要写self.x、self.y- 列表里的
B(4,5)如果没有提前定义类B,导入时会直接抛出 NameError
同文件保留两个内容的解决方案
分两种场景处理:
场景1:LIST_OF_A 仅在模块自身作为脚本运行时使用,不需要对外导出
把 LIST_OF_A 相关的代码放到 if __name__ == "__main__" 判断块内即可,导入模块时该块内的代码不会执行:
import dataclasses @dataclasses.dataclass class A: x: int y: int def big_method(self): do_big_stuff(self.x, self.y) if __name__ == "__main__": # 仅当直接运行python module.py时才会执行下面的代码 LIST_OF_A = [ A(2,3), A(4,5) ] # 你原本要执行的其他脚本逻辑
场景2:LIST_OF_A 需要对外导出,供其他导入该模块的代码使用
可以用懒加载的方式避免导入时就实例化:
方法1:用函数封装获取逻辑
# 其他类定义不变 _LIST_OF_A = None def get_list_of_a(): global _LIST_OF_A if _LIST_OF_A is None: _LIST_OF_A = [ A(2,3), A(4,5) ] return _LIST_OF_A
其他模块使用时调用 module.get_list_of_a() 即可,只有第一次调用时才会完成实例化。
方法2:Python 3.7+ 用模块级__getattr__实现懒加载
在module.py末尾添加:
def __getattr__(name): if name == "LIST_OF_A": return [ A(2,3), A(4,5) ] raise AttributeError(f"module {__name__} has no attribute {name}")
其他模块可以正常用 from module import LIST_OF_A 或者 module.LIST_OF_A 访问,只有第一次访问时才会实例化。
内容的提问来源于stack exchange,提问作者mrkgoh
相关产品推荐
相关产品推荐

