I’m having trouble getting MyPy to pass my script which contains a dataclass Bar with an optional argument foos that holds a list of Foo objects and defaults to an empty list.
Stranger still, adding a method Bar.sum_foos() which iterates through self.foos raises a second MyPy error. Am I misunderstanding how to set the correct types, or is something else going on?
script.py
from __future__ import annotations
from typing import Optional
from dataclasses import dataclass, field
class Foo():
pass
@dataclass
class Bar():
foos: Optional[list[Foo]] = field(default_factory = list)
def sum_foos(self) -> float:
for foo in self.foos:
pass
return 0.0
2 MyPy errors
$ mypy script.py
script.py:12: error: Incompatible types in assignment (expression has type "List[_T]", variable has type "Optional[List[Foo]]")
script.py:15: error: Item "None" of "Optional[List[Foo]]" has no attribute "__iter__" (not iterable)
Found 2 errors in 1 file (checked 1 source file)
Versions
$ python --version
Python 3.8.12
$ mypy --version
mypy 0.950 (compiled: yes)
>Solution :
You have foos as an optional argument so if it’s None you can’t iterate of it and it will throw an error. You can add simple check before doing so. About second error its list of Foo so you need to add typing.
Fixed code:
from __future__ import annotations
from typing import Optional, List
from dataclasses import dataclass, field
class Foo():
pass
@dataclass
class Bar():
foos: Optional[list[Foo]] = field(default_factory=list[Foo])
def sum_foos(self) -> float:
if self.foos:
for foo in self.foos:
pass
return 0.0