我有一个函数可以接受任何dataclass
的实例。
什么是合适的类型提示呢?
在python文档中找不到任何官方内容
这是我一直在做的,但我认为这是不正确的
from typing import Any, NewType
DataClass = NewType('DataClass', Any)
def foo(obj: DataClass):
...
另一个想法是将Protocol
与这些类属性__dataclass_fields__
,__dataclass_params__
一起使用。
答案 0 :(得分:2)
尽管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的类型提示)。