简体   繁体   English

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

[英]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. Typedataclass 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM