尽管它的名字,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
这种方法也是您在问题中提到的,但它有三个缺点:
受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 的类型提示),现在和以后都不会。