mypy 错误:向抽象方法添加类型时无法使用抽象属性实例化抽象类

Posted

技术标签:

【中文标题】mypy 错误:向抽象方法添加类型时无法使用抽象属性实例化抽象类【英文标题】:mypy error: Cannot instantiate abstract class with abstract attributes when adding types to an abstract method 【发布时间】:2021-12-29 03:49:01 【问题描述】:

我有一个类,我想为其添加类型提示,如下所示:

import yaml

class TestClass(dict):

    @classmethod
    def load(cls, fname) -> "TestClass":
        return cls(yaml.safe_load(""))

    @property
    @abc.abstractmethod
    def test(self):
        raise

当我在仅包含此类的模块上运行 mypy 时,我收到以下错误消息:

error: Cannot instantiate abstract class 'TestClass' with abstract attribute 'test'

根据我从其他帖子中了解到的情况,这与在执行加载方法时实例化“测试”方法有关。有没有办法单独使用 typehints 来解决这个问题,还是我需要在这里调整我的代码?

【问题讨论】:

你能澄清你想要做什么吗?在不是abc.ABC 的类上使用abc.abstractmethod 没有多大意义。 【参考方案1】:

mypy 告诉你的是TestClass.load(...) 会失败,因为它会尝试创建抽象类TestClass 的实例。

我们可以通过要求cls 可以用任何yaml.safe_load 返回的东西来解决这个问题(我在这里假设dict),并返回一个TestClass 的实例:

from typing import Callable
import abc
import yaml

class TestClass(dict):

    @classmethod
    def load(cls: Callable[[dict], TestClass], fname) -> "TestClass":
        return cls(yaml.safe_load(""))

    @property
    @abc.abstractmethod
    def test(self):
        raise

请注意,TestClass.load("foo") 现在也将通过类型检查。这在某种程度上是公平的,因为它在运行时也很好,直到您在创建的实例上调用test()。我认为这可能是 mypy 如何实现协议的限制。

【讨论】:

def load(cls: Any, fname) 在这种情况下应该和casting 做同样的事情。 @MisterMiyagi 你能更清楚地解释为什么会出现这个错误吗?调用 return cls(yaml.safe_load("") 时,我们用 yaml 返回的字典实例化类,但这与抽象方法到底有什么关系?为什么通过预先实例化 cls 来解决这个问题? @Thomas 你能解释一下吗?我不太明白为什么只用抽象方法返回类的实例会导致问题 @hhhh 你知道什么是抽象类吗? @Thomas 据我了解,这就像一个超类,其方法在不同的子类中使用

以上是关于mypy 错误:向抽象方法添加类型时无法使用抽象属性实例化抽象类的主要内容,如果未能解决你的问题,请参考以下文章

使用 mypy 进行类型检查,我无法弄清楚为啥会发生此错误 [关闭]

Flutter 抽象类类型异常

我不断收到“无法将参数'_inputVerifier'声明为抽象类型'InputVerifier'”错误

Java知识点总结

23种设计模式之抽象工厂

在不破坏现有基类的情况下向具有许多派生类的抽象基类添加新方法