Using the attrs libary and Python 3.6, I thought the following would allow me to specify that x
and y
can only contain integers:
import attr
@attr.s
class C:
x : List[int] = attr.ib() # not working
y = attr.ib(type=List[int]) # not working either
Both of the commented lines throw a NameError: name 'List' is not defined
.
The reasons I expected that to work are these:
(1) The types section of the attr documentation includes the following passage: "attrs
also allows you to associate a type with an attribute using either the type argument to attr.ib() or – as of Python 3.6 – using PEP 526-annotations". It then demonstrates both methods:
@attr.s
class C:
x = attr.ib(type=int)
y: int = attr.ib()
(2) PEP 526 states that the following syntax for type annotation is valid: primes: List[int] = []
.
The syntax is indeed valid. But the generic type annotation objects added by PEP 484 are not in the builtins namespace, but in the
typing
module.So, you need to do what all of the examples in the
attrs
docs you linked, and PEP 484, PEP 483, PEP 526, and thetyping
docs do:Also, note that this is just an annotation. You can still write
c = C(x=[], y=[1.0])
and you won't get aTypeError
. As the docs you linked say:It's not at all clear what
attrs
should do with this metadata. It's a central part of the design of PEP 483/PEP 484 that type annotations are nothing more than annotations are runtime, and do not affect the types of values or what's legal to store where; they're only there to be used by static type checkers and other tools that runs separately from Python.In particular, Mypy (the reference-standard static type checker), some linters, and some IDEs should flag this as an error. If they don't support
attrib
annotations yet, they're almost certainly working on it (since they're roughly equivalent to annotated attributes in 3.7/PEP 557dataclass
).