如何让抽象数据类传递给mypy?

Ben*_*itz 16 python abstract-base-class mypy python-dataclasses python-typing

mypy v0.910 拒绝 Python 3.9 中的抽象数据类。这是最小的可重复示例:

from abc import ABC, abstractmethod
from dataclasses import dataclass

@dataclass
class Liquid(ABC):

    @abstractmethod
    def drip(self) -> None:
        pass
Run Code Online (Sandbox Code Playgroud)

这是错误消息:

$ mypy --python-version 3.9 so.py
so.py:4: error: Only concrete class can be given where "Type[Liquid]" is expected
Found 1 error in 1 file (checked 1 source file)
Run Code Online (Sandbox Code Playgroud)

如何让此代码通过mypy


笔记

我从mypy 问题 #5374中了解到,这是mypy中的一个错误,于 2018 年首次注意到,但仍未得到纠正。不过,我认为人们必须将mypy与抽象数据类一起使用,因此必须有一种解决方法或正确的方法来定义或注释该类。有什么推荐的?

错误消息的基础似乎是mypy假设任何类型的对象都Type可以实例化,但抽象类不能实例化。这似乎是错误,因为Type定义为表示类对象,而不一定是具体的类对象(即可以实例化的类对象)。

添加# type: ignore到包含的行class Liquid不会阻止错误消息。由于代码不包含Type[Liquid],我认为它一定在 生成的代码中dataclassType在 Python 3.9 中已弃用,但显然dataclass代码生成器仍然生成它。

Nic*_*ner 11

创建一个数据类作为 mixin 并让 ABC 继承它:

from abc import ABC, abstractmethod
from dataclasses import dataclass    

@dataclass
class LiquidDataclassMixin:
    my_var: str

class Liquid(ABC, LiquidDataclassMixin):
    @abstractmethod
    def drip(self) -> None:
        pass
Run Code Online (Sandbox Code Playgroud)

这也适用于 mypy 类型检查。我建议不要使用,# type: ignore因为这会破坏类型检查的意义。摘自这个 GitHub 问题


Kam*_*ski 3

添加# type: ignore到装饰器行。所以在你的情况下它将是:

from abc import ABC, abstractmethod
from dataclasses import dataclass

@dataclass  # type: ignore[misc]
class Liquid(ABC):

    @abstractmethod
    def drip(self) -> None:
        pass
Run Code Online (Sandbox Code Playgroud)