__annotations__ 不 return 来自父数据类的字段
__annotations__ doesn't return fields from a parent dataclass
我正在了解 dataclass
,但我无法理解为什么 __annotations__
不提供来自父 class 的字段。请参阅以下示例:
import dataclasses as dc
@dc.dataclass
class B:
a: int
B.__annotations__
# returns {'a': int}
C = dc.make_dataclass("c", fields=["w"], bases=(B,))
C.__annotations__
# returns {'w': 'typing.Any'} (without a)
__annotations__
不会给你父 class 的类型注释,因为它应该只包含在 class 自身中定义的注释。有一个特定的函数 returns 一个 class 的所有注释,包括其父项的注释,称为 typing.get_type_hints
:
This is often the same as obj.__annotations__
. [...] For a class C, return a dictionary constructed by merging all the __annotations__
along C.__mro__
in reverse order.
在您的特定示例中使用它时要记住的一件事是数据classes使用大量黑魔法来构造classes,并且它会在查找所有类型时中断如果某些字段在 make_dataclass
定义中未键入则提示(作为错误 here 提交):
import dataclasses as dc
from typing import Any, get_type_hints
@dc.dataclass
class B:
a: int
get_type_hints(B)
# returns {'a': <class 'int'>}
# fields=["w"] should be equivalent, but get_type_hints doesn't like it. Bug, maybe?
C = dc.make_dataclass("C", fields=[("w", Any)], bases=(B,))
typing.get_type_hints(C)
# returns {'a': <class 'int'>, 'w': typing.Any}
但是正如 user2357112 指出的那样,最好建议您使用 dataclasses.fields
函数,该函数 returns dataclass 装饰器根据数据class 及其基础。这是您在分析数据时通常想要使用的classes,它包含您需要的所有信息以及更多信息。
此外,它与您最初使用的 make_dataclass
中字段的 shorthand 定义一起工作,并清除伪字段:
dc.fields(D)
# returns a tuple of
Field(name='a',type=<class 'int'>,default=<dataclasses._MISSING_TYPE object at 0x7f103d9985c0>,default_factory=<dataclasses._MISSING_TYPE object at 0x7f103d9985c0>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),_field_type=_FIELD)
# and
Field(name='w',type=typing.Any,default=<dataclasses._MISSING_TYPE object at 0x7f103d9985c0>,default_factory=<dataclasses._MISSING_TYPE object at 0x7f103d9985c0>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),_field_type=_FIELD)
我正在了解 dataclass
,但我无法理解为什么 __annotations__
不提供来自父 class 的字段。请参阅以下示例:
import dataclasses as dc
@dc.dataclass
class B:
a: int
B.__annotations__
# returns {'a': int}
C = dc.make_dataclass("c", fields=["w"], bases=(B,))
C.__annotations__
# returns {'w': 'typing.Any'} (without a)
__annotations__
不会给你父 class 的类型注释,因为它应该只包含在 class 自身中定义的注释。有一个特定的函数 returns 一个 class 的所有注释,包括其父项的注释,称为 typing.get_type_hints
:
This is often the same as
obj.__annotations__
. [...] For a class C, return a dictionary constructed by merging all the__annotations__
alongC.__mro__
in reverse order.
在您的特定示例中使用它时要记住的一件事是数据classes使用大量黑魔法来构造classes,并且它会在查找所有类型时中断如果某些字段在 make_dataclass
定义中未键入则提示(作为错误 here 提交):
import dataclasses as dc
from typing import Any, get_type_hints
@dc.dataclass
class B:
a: int
get_type_hints(B)
# returns {'a': <class 'int'>}
# fields=["w"] should be equivalent, but get_type_hints doesn't like it. Bug, maybe?
C = dc.make_dataclass("C", fields=[("w", Any)], bases=(B,))
typing.get_type_hints(C)
# returns {'a': <class 'int'>, 'w': typing.Any}
但是正如 user2357112 指出的那样,最好建议您使用 dataclasses.fields
函数,该函数 returns dataclass 装饰器根据数据class 及其基础。这是您在分析数据时通常想要使用的classes,它包含您需要的所有信息以及更多信息。
此外,它与您最初使用的 make_dataclass
中字段的 shorthand 定义一起工作,并清除伪字段:
dc.fields(D)
# returns a tuple of
Field(name='a',type=<class 'int'>,default=<dataclasses._MISSING_TYPE object at 0x7f103d9985c0>,default_factory=<dataclasses._MISSING_TYPE object at 0x7f103d9985c0>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),_field_type=_FIELD)
# and
Field(name='w',type=typing.Any,default=<dataclasses._MISSING_TYPE object at 0x7f103d9985c0>,default_factory=<dataclasses._MISSING_TYPE object at 0x7f103d9985c0>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),_field_type=_FIELD)