类型提示非特定数据类的实例

问题描述 投票:3回答:1

我有一个接受任何dataclass实例的函数。什么是适当的类型暗示呢?

没有在python文档中找到官方的东西


这就是我一直在做的事情,但我不认为这是正确的

from typing import Any, NewType

DataClass = NewType('DataClass', Any)
def foo(obj: DataClass):
    ...

另一个想法是使用Protocol与这些类属性__dataclass_fields____dataclass_params__

python protocols python-3.7 python-dataclasses
1个回答
3
投票

尽管它的名字,dataclasses.dataclass不公开类接口。它只允许您以方便的方式声明自定义类,这使得它显然将被用作数据容器。因此,从理论上讲,几乎没有机会编写只适用于数据类的东西,因为数据类实际上只是普通的类。

在实践中,有几个原因可以解释为什么你想要声明仅限数据类的函数,我看到了两种方法。


正确的方法,使用静态类型检查器和编写协议

from dataclasses import dataclass
from typing import Dict

from typing_extensions import Protocol

class IsDataclass(Protocol):
    # as already noted in comments, checking for this attribute is currently
    # the most reliable way to ascertain that something is a dataclass
    __dataclass_fields__: Dict

def dataclass_only(x: IsDataclass):
    ...  # do something that only makes sense with a dataclass

@dataclass
class A:
    pass

dataclass_only(A())  # a static type check should show that this line is fine

这种方法也是您在问题中提到的方法,但它有三个缺点:

  • 您需要第三方库(如mypy)为您执行静态类型检查
  • 你需要安装typing_extensions,因为Protocol不是核心typing模块的一部分
  • 最后但并非最不重要的是,以这种方式使用数据类协议doesn't work right now

有点EAFP灵感的东西实际上有效

from dataclasses import is_dataclass

def dataclass_only(x):
    """Do something that only makes sense with a dataclass.

    Raises:
        ValueError if something that is not a dataclass is passed.

    ... more documentation ...
    """
    if not is_dataclass(x):
        raise ValueError(f"'{x.__class__.__name__}' is not a dataclass!")
    ...

在这种方法中,由于文档的原因,该代码的维护者或用户仍然非常清楚这种行为。但缺点是您没有对代码进行静态分析(包括IDE的类型提示),而不是现在而不是永远。

© www.soinside.com 2019 - 2024. All rights reserved.