如何指定一个属性必须是(例如)整数的列表,而不仅仅是列表?


问题内容

使用attrs库和Python
3.6,我认为以下内容将允许我指定该值,x并且y只能包含整数:

import attr

@attr.s
class C:
  x : List[int] = attr.ib()   # not working
  y = attr.ib(type=List[int]) # not working either

两条注释行都抛出一个NameError: name 'List' is not defined

我希望能够正常工作的原因如下:

(1)attr文档类型部分包括以下段落:“attrs还允许您使用attr.ib()的类型参数或–从Python
3.6开始–使用PEP 526注释将类型与属性相关联” 。然后演示了两种方法:

@attr.s
class C:
    x = attr.ib(type=int)
    y: int = attr.ib()

(2)PEP
526
声明以下用于类型注释的语法有效:primes: List[int] = []


问题答案:

语法 确实有效。但是,PEP
484
添加的通用类型注释对象不在内置名称空间中,而是在typing模块中。

因此,您需要执行所attrs链接文档中的所有示例,PEP 484,PEP
483
,PEP 526和typing文档都应执行以下操作:

from typing import List

另外,请注意,这只是一个注释。您仍然可以写作c = C(x=[], y=[1.0]),但不会得到TypeError。正如您链接的文档所说:

attrs本身还没有任何可用于类型元数据的功能。但是,这对于编写自己的验证器或序列化框架很有用。

完全不清楚attrs 如何处理此元数据。PEP 483 / PEP
484是设计的核心部分,类型注释只不过是运行时注释,不会影响值的类型或存储位置的合法性;只有静态类型检查器和其他与Python分开运行的工具才能使用它们。

特别是Mypy(参考标准静态类型检查器),某些linter和某些IDE应该将此标记为错误。如果他们还不支持attrib注释,那么几乎可以肯定他们正在努力(因为它们大致等效于3.7
/ PEP 557中的dataclass
注释属性)。