dataclasses.Field不能将类型注释解析为实际类型 [英] dataclasses.Field doesn't resolve type annotation to actual type

查看:167
本文介绍了dataclasses.Field不能将类型注释解析为实际类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

python标准的 Field 类的文档数据类模块仅指定:

The documentation for the Field class of python's standard dataclasses module specifies only:

其记录的属性为:

Its documented attributes are:

  • [...]
  • type:字段的类型.

对我来说,这似乎意味着该字段将包含类型本身,而不仅是字符串形式的名称.

To me, it seems to mean that the field will contain the type itself, and not only it's name in the form of a string.

但是,似乎它只是简单地按原样复制类型注释,从而使它变得毫无用处.

However, it seems that it simply copies the type annotation as is, making it quite useless.

示例:

@dataclasses.dataclass 
class C: 
    c: 'C'

dataclasses.fields(C)[0].type # This returns the string 'C'
typing.get_type_hints(C)['c'] # This returns the class C, as expected

使用 PEP563 类型注释时,该问题甚至会系统地出现.

The problem even occurs systematically when using PEP563 type annotations.

这是dataclasses模块中的错误吗?这是预期的行为吗?如果是这样,如何在给定Field实例的情况下检索类型对象?

Is this a bug in the dataclasses module? Is this the expected behavior? If so, how do I retrieve a type object given a Field instance?

推荐答案

这是故意的.在导入时解析类型提示是昂贵的,尤其是当首先使用from __future__ import annotations禁用其解析时.

This is deliberate. Resolving type hints at import time is expensive, especially when from __future__ import annotations has been used to disable resolving them in the first place.

最初,当您使用from __future__ import annotations开关并包含数据类问题# 92 .一旦数据类将其放入Python 3.7中,它便成为 Python错误#33453 .

Initially, the addition of the PEP 563 to Python 3.7 broke dataclasses when you used the from __future__ import annotations switch and included ClassVar or InitVar type annotations for fields; these would not be resolved at this point and remained a string. This was already a problem before PEP 563 if you explicitly used strings, see dataclasses issue #92. This became a Python bug, #33453, once dataclasses made it into Python 3.7 proper.

启发dataclasses的父"项目attrs

The 'parent' project, attrs, which inspired dataclasses, also had this issue to solve. There, Łukasz Langa (co-author of most of the type hinting peps, including PEP 563), states:

好的,所以我尝试了上面的方法,这似乎是一个核选项,因为它会强制评估所有注释.这就是我要使用from __future__ import annotations避免的事情.

并在讨论了固定问题33453的拉取请求中的讨论dataclasses的作者埃里克·史密斯(Eric Smith)说:

and in the discussion on the pull request that fixed issue 33453, Eric Smith, author of dataclasses, stated:

我一直在研究这样做.我认为@ambv的要点是由于在每个字段上调用eval而引入了性能影响,而字符串注释的目的是消除性能影响.

I've been researching doing just that. I think @ambv's point is that it introduces a performance hit due to calling eval on every field, while the point of string annotations is to remove a performance hit.

此外,还有其他问题;您无法在导入时评估所有类型的提示,而不是在它们使用前向引用时进行评估:

Moreover, there were other problems; you can't evaluate all type hints at import time, not when they use forward references:

除了性能问题外,在以下情况下(没有__future__语句,也没有数据类),我在get_type_hints()上遇到错误,因为调用get_type_hints()时未定义C.这是 python/typing#508 .请注意,在此示例中,调用get_type_hints()的位置恰好是@dataclass的运行位置,并且需要调用精简的get_type_hints().

In addition to the performance issue, in the following case (without a __future__ statement and without dataclasses), I get an error on get_type_hints() because C is undefined when get_type_hints() is called. This is python/typing#508. Notice that where get_type_hints() is called in this example is exactly where @dataclass is going to run and would need to call the stripped down get_type_hints().

因此,最后,dataclasses所做的只是将字符串试探法应用于注释,而不会为您加载它们.

So in the end, all that dataclasses does is do is apply string heuristics to the annotations, and will not load them for you.

要检索类型,只需在类本身上使用get_type_hints(),然后将字段.name属性用作结果键:

To retrieve the type, just use get_type_hints() on the class itself, and us the field .name attribute as the key into the result:

resolved = typing.get_type_hints(C)
f = dataclasses.fields(C)[0]
ftype = resolved[f.name]

这篇关于dataclasses.Field不能将类型注释解析为实际类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆