新注释打破了数据类检查
New annotations break inspection of dataclasses
使用 PEP 563,from __future__ import annotations
更改了类型注释,以便它们被延迟评估,这提供了很多好处,例如前向引用。
但是,这似乎与其他功能(如数据classes)配合得不好。例如,我有一些代码检查 class 的 __init__
方法的类型参数。 (真正的用例是为 class 提供一个默认的序列化器,但这在这里并不重要。)
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__
方法的类型提示,以便它像在正常 classes 上一样处理数据classes?
当 reported to the Python mailing list, this was considered a "good catch" by the BDFL. According to the issue, this has been fixed. The pull request 合并和向后移植修复程序时。它从 Python 3.7.6 和 Python 3.8.1.
开始按预期工作
使用 PEP 563,from __future__ import annotations
更改了类型注释,以便它们被延迟评估,这提供了很多好处,例如前向引用。
但是,这似乎与其他功能(如数据classes)配合得不好。例如,我有一些代码检查 class 的 __init__
方法的类型参数。 (真正的用例是为 class 提供一个默认的序列化器,但这在这里并不重要。)
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__
方法的类型提示,以便它像在正常 classes 上一样处理数据classes?
当 reported to the Python mailing list, this was considered a "good catch" by the BDFL. According to the issue, this has been fixed. The pull request 合并和向后移植修复程序时。它从 Python 3.7.6 和 Python 3.8.1.
开始按预期工作