我有一个接受任何dataclass
实例的函数。什么是适当的类型暗示呢?
没有在python文档中找到官方的东西
这就是我一直在做的事情,但我不认为这是正确的
from typing import Any, NewType
DataClass = NewType('DataClass', Any)
def foo(obj: DataClass):
...
另一个想法是使用Protocol
与这些类属性__dataclass_fields__
,__dataclass_params__
。
尽管它的名字,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
模块的一部分有点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的类型提示),而不是现在而不是永远。