Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does the type hint of a set type variable make the ` mypy ` module not recognize the attributes of a namedtuple in this set type variable?

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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.

>Solution :

You need to annotate students as a set of Students (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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading