为什么 PyPy 在我尝试定义类型注释 class 成员(例如列表或字典)时失败?

Why PyPy fails when I try to define type annotated class member (e.g. list or dict)?

我有以下简单代码:

from dataclasses import dataclass, field

@dataclass
class Test:
    names: list[str] = field(default_factory=list)

if __name__ == '__main__':
    Test(['a', 'b', 'c'])

目前正在尝试通过 pyenv 使用最新的 PyPy 执行它:

Python 3.8.12 (9ef55f6fc369, Oct 24 2021, 20:11:54)
[PyPy 7.3.7 with GCC 7.3.1 20180303 (Red Hat 7.3.1-5)]

我收到以下错误:

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    @dataclass
  File "test.py", line 6, in Test
    names: list[str] = field(default_factory=list)
AttributeError: type object 'list' has no attribute '__class_getitem__'

基本上任何可迭代类型都会发生同样的情况,例如dict[str, str] 等等。有什么想法吗?

以这种方式使用 list 仅在 Python 3.9 中引入。有关详细信息,请参阅 PEP-585。在此之前,您必须从 typing 模块导入 List 以用于类型提示(除非您只想指定 list 而没有包含的类型)。

这意味着您的示例需要是:

from dataclasses import dataclass, field
from typing import List

@dataclass
class Test:
    names: List[str] = field(default_factory=list)

if __name__ == '__main__':
    Test(['a', 'b', 'c'])

或者,您可以从 __future__ 导入 annotations 并在类型提示中使用它时获得参数化 list 的能力。请注意,这确实取决于您的工具是否将其识别为有效,并且我个人不使用它,因此根据评论,我不能保证没有问题。

from __future__ import annotations
from dataclasses import dataclass, field

@dataclass
class Test:
    names: list[str] = field(default_factory=list)

if __name__ == '__main__':
    Test(['a', 'b', 'c'])