I have a question about the mypy
module. It is demonstrated in the code below:
from typing import Set, NamedTuple
from collections import namedtuple
Student = namedtuple('Student', 'name english math')
students: Set[NamedTuple] = {Student('John', 100, 80),
Student('Mary', 90, 90),}
for student in students:
print(student.name)
When I used the mypy
module to check the snippet of code, it reported the following error for the last line:
test.py:8: error: "NamedTuple" has no attribute "name" [attr-defined]
Found 1 error in 1 file (checked 1 source file)
I also found that this error was not reported after I omitted the type hint for the variable students
in line 4 as follows:
from typing import Set, NamedTuple
from collections import namedtuple
Student = namedtuple('Student', 'name english math')
students = {Student('John', 100, 80),
Student('Mary', 90, 90),}
for student in students:
print(student.name)
Can anyone kindly tell me why this error occurs? And what is the appropriate way to let the mypy
module know the attributes of the namedtuple Student
without omitting the type hint for the variable students
in a situation like this? Thank you in advance.
CodePudding user response:
You need to annotate students
as a set of Student
s (which you've defined as having a name
attribute), not the base NamedTuple
type (which isn't specifically associated with your Student
namedtuple):
from typing import Set
from collections import namedtuple
Student = namedtuple('Student', 'name english math')
students: Set[Student] = {Student('John', 100, 80),
Student('Mary', 90, 90),}
for student in students:
print(student.name)
If you want to use typing.NamedTuple
, you use it as the base class for your specific namedtuple type:
from typing import NamedTuple, Set
class Student(NamedTuple):
name: str
english: int
math: int
students: Set[Student] = {Student('John', 100, 80),
Student('Mary', 90, 90),}
for student in students:
print(student.name)
Note that the typing.NamedTuple
version has type annotations for the individual attributes; the collections.namedtuple
version implicitly types them all as Any
.