mypy报Cannot instantiate abstract class错误能否仅用类型提示修复
问题原因
这个报错是mypy的静态检查规则触发的:只要类中存在未实现的抽象方法,就不允许直接实例化该类。你定义的TestClass包含@abc.abstractmethod修饰的test属性,本身属于抽象类,因此mypy会拦截load方法中cls()的实例化操作。
仅通过类型提示修复的方案
如果你能保证实际使用时只会通过TestClass的非抽象子类调用load方法,可以通过添加泛型类型标注解决报错,不需要修改业务逻辑:
import abc import yaml from typing import TypeVar, Type T = TypeVar('T', bound='TestClass') class TestClass(dict): @classmethod def load(cls: Type[T], fname) -> T: return cls(yaml.safe_load("")) @property @abc.abstractmethod def test(self): raise NotImplementedError
这个标注的作用是告诉mypy:调用load方法的cls一定是TestClass的非抽象子类,实例化操作是安全的。
如果只是想临时绕过检查,也可以直接在报错行加忽略注解:
@classmethod def load(cls, fname) -> "TestClass": return cls(yaml.safe_load("")) # type: ignore[abstract]
注意:忽略注解属于治标不治本的方案,如果直接调用TestClass.load(),运行时Python本身也会抛出无法实例化抽象类的错误。
更合理的代码调整方案
方案1:保留抽象基类设计
如果你本来就打算让TestClass仅作为基类使用,不允许直接实例化,建议显式继承abc.ABC,并在实际使用时先实现非抽象子类:
import abc import yaml from typing import TypeVar, Type T = TypeVar('T', bound='TestClass') class TestClass(dict, abc.ABC): @classmethod def load(cls: Type[T], fname) -> T: return cls(yaml.safe_load("")) @property @abc.abstractmethod def test(self): raise NotImplementedError # 实现子类后调用load class SubTestClass(TestClass): @property def test(self): return "default value" inst = SubTestClass.load("config.yaml")
这种方案下mypy不会报错,运行时也不会出现抽象类实例化的问题。
方案2:移除抽象方法标记
如果你本来就允许直接实例化TestClass,只需要给test属性添加默认实现,去掉@abc.abstractmethod修饰即可:
import yaml class TestClass(dict): @classmethod def load(cls, fname) -> "TestClass": return cls(yaml.safe_load("")) @property def test(self): # 补充默认实现即可 return "default value"
内容的提问来源于stack exchange,提问作者dmmpie
相关产品推荐
相关产品推荐

