【问题标题】:New annotations break inspection of dataclasses新的注释打破了对数据类的检查
【发布时间】:2018-09-04 18:18:47
【问题描述】:

在 PEP 563 中,from __future__ import annotations 更改了类型注释,以便对其进行延迟评估,这提供了很多好处,例如前向引用。

但是,这似乎与其他功能(如数据类)搭配得不好。例如,我有一些代码检查类的__init__ 方法的类型参数。 (真正的用例是为类提供一个默认的序列化器,但这在这里并不重要。)

from dataclasses import dataclass
from typing import get_type_hints

class Foo:
    pass

@dataclass
class Bar:
    foo: Foo

print(get_type_hints(Bar.__init__))

在 Python 3.6 和 3.7 中,这符合预期;它打印{'foo': <class '__main__.Foo'>, 'return': <class 'NoneType'>}

但是,如果在 Python 3.7 中,我添加了from __future__ import annotations,那么这将失败并出现错误:

NameError: name 'Foo' is not defined

我想我明白为什么会这样。 __init__ 方法在 dataclasses 中定义,它的环境中没有 Foo 对象,并且 Foo 注释被传递给 dataclass 并附加到 __init__ 作为字符串 "Foo" 而不是与原始对象 Foo 相比,但新注释的 get_type_hints 仅在定义 __init__ 的模块中进行名称查找,而不是定义注释的位置。

我觉得我一定做错了什么。我很惊讶这两个新功能一起玩得这么差。是否有适当的方法来检查 __init__ 方法的类型提示,以便它像在普通类上一样在数据类上工作?

【问题讨论】:

  • get_type_hints(Bar) 似乎工作正常,尽管它没有 return 注释。它给了我{'foo': <class '__main__.Foo'>}
  • @PatrickHaugh 是的,但get_type_hints(Bar) 不是我想要的。我的用例是一个检查,它接受一个类并查看该类的__init__ 方法。如果Bar 不是数据类,那么get_type_hints(Bar) 将不起作用。如果数据类Bar 的字段是init=False,那么它也不起作用。

标签: python annotations python-3.7 python-dataclasses


【解决方案1】:

reported 加入 Python 邮件列表时,这是considered BDFL 的“好消息”。根据issue,此问题已得到修复。用于修复的pull request 已合并并向后移植。它从 Python 3.7.6 和 Python 3.8.1 开始按预期工作。

【讨论】:

  • 你认为这可能是相关的:stackoverflow.com/questions/55937472/… ?
  • @lovasoa 它们可能是相关的,因为dataclassesdoctest 在与定义的范围不同的范围内运行代码,这为注释创建了极端情况。
  • 链接的拉取请求尚未合并,这意味着这在 3.7.4 中仍然存在问题(发表此评论时的最新版本)。
猜你喜欢
  • 2018-02-04
  • 2023-04-02
  • 1970-01-01
  • 2014-11-10
  • 2011-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多