Python自定义TypeVar导入触发NameError的原因及重构方案
错误原因分析
这是循环导入+变量定义时机不匹配导致的问题,具体流程如下:
test.py执行from aa import *,触发aa/__init__.py启动加载- 原
aa/__init__.py先导入ASub,这会执行aclass.py的代码 aclass.py第一行就执行from bb import *,触发bb模块加载,进而执行bclass.pybclass.py执行from aa import *时,aclass.py还没运行到AT = TypeVar(...)这行代码——因为它被提前触发的bb模块导入打断了,所以aa模块的命名空间里还没有AT,最终抛出NameError。
重构方案(保持
aclass.py完全不变) 调整aa/__init__.py的导入顺序
修改aa/__init__.py,先导入AT,再导入ASub和ASub2,确保在触发bb模块加载前,AT已经被注册到aa模块的命名空间中:
# aa/__init__.py from .aclass import AT from .aclass import ASub from .aclass import ASub2 __all__ = ['ASub', 'ASub2', 'AT']
优化bclass.py的导入方式(可选但推荐)
避免使用from xx import *带来的命名污染,改为显式导入需要的对象:
# bb/bclass.py from typing import Generic from aa import AT, ASub class BClass(Generic[AT]): def __init__(self, a: AT, b: AT) -> None: self.a = a self.b = b def B_method(self) -> AT: i: int = self.a.a + self.b.a return ASub(i)
修复后的加载逻辑
test.py导入aa模块,先执行from .aclass import AT,此时aclass.py会完成AT的定义,并将其导入到aa模块的命名空间- 接着导入
ASub,此时aclass.py执行from bb import *加载bclass.py bclass.py导入aa的AT和ASub时,这两个对象已经存在,不会再出现未定义错误。
内容的提问来源于stack exchange,提问作者jmg2027
相关产品推荐
相关产品推荐

