[英]How to get an abstract dataclass to pass mypy?
mypy v0.910 rejects abstract dataclasses in Python 3.9. mypy v0.910 拒绝 Python 3.9 中的抽象数据类。 Here's the Minimal Reproducible Example:这是最小的可重现示例:
from abc import ABC, abstractmethod
from dataclasses import dataclass
@dataclass
class Liquid(ABC):
@abstractmethod
def drip(self) -> None:
pass
Here's the error message:这是错误消息:
$ 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)
How do I get this code to pass mypy ?我如何让这段代码通过mypy ?
Notes笔记
I gather from mypy issue #5374 that this is a bug in mypy , first noticed in 2018 and still not corrected.我从mypy 问题 #5374中了解到,这是mypy中的一个错误,于 2018 年首次被发现,但仍未得到纠正。 I figure that people must be using mypy with abstract dataclasses, though, so there must be a workaround or a correct way to define or annotate the class. What is recommended?不过,我认为人们必须将mypy与抽象数据类一起使用,因此必须有一种解决方法或正确的方法来定义或注释 class。推荐什么?
The basis for the error message seems to be that mypy assumes that any object of type Type
can be instantiated, but abstract classes cannot be instantiated.错误信息的依据似乎是mypy假设类型为Type
的任何object都可以被实例化,但是抽象类不能被实例化。 This appears to be the error since Type
is defined to mean a class object, not necessarily a concrete class object (ie one that can be instantiated).这似乎是错误,因为Type
被定义为表示 class object,不一定是具体的 class object(即可以实例化的)。
Adding # type: ignore
to the line containing class Liquid
does not block the error message.添加# type: ignore
到包含class Liquid
的行不会阻止错误消息。 Since the code does not contain Type[Liquid]
, I figure it must be in the code generated by dataclass
.由于代码不包含Type[Liquid]
,我认为它必须在dataclass
生成的代码中。 Type
is deprecated in Python 3.9, but apparently the dataclass
code generator still generates it. Type
在dataclass
3.9 中被弃用,但显然数据类代码生成器仍然生成它。
Create a dataclass as a mixin and let the ABC class inherit from it:创建一个数据类作为 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
This works with mypy type checking as well.这也适用于 mypy 类型检查。 I recommend against using # type: ignore
as that defeats the point of type-checking.我建议不要使用# type: ignore
因为这违背了类型检查的意义。 Taken from this GitHub issue .取自此 GitHub 问题。
Add # type: ignore
to the decorator line.将# type: ignore
添加到装饰器行。 So in your case it would be:所以在你的情况下,它将是:
from abc import ABC, abstractmethod
from dataclasses import dataclass
@dataclass # type: ignore
class Liquid(ABC):
@abstractmethod
def drip(self) -> None:
pass
As indicated in the merge request "Use a dedicated error code for abstract type object type error" , we will soon be able to disable it globally either using --disable-error-code=type-abstract
in the command line or adding disable_error_code =type-abstract
to the configuration file.正如合并请求“为抽象类型 object 类型错误使用专用错误代码”中所指出的,我们将很快能够在命令行中使用--disable-error-code=type-abstract
或添加disable_error_code =type-abstract
配置文件的disable_error_code =type-abstract
。 (Possibly from the coming v0.983
) (可能来自即将到来的v0.983
)
For non-global use cases, it might be sufficient to add # type: ignore[type-abstract]
at the end of the respective line.对于非全局用例,在相应行的末尾添加# type: ignore[type-abstract]
可能就足够了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.