mypy: Incompatible return value type

Question:

So, I have one dataclass as follows

@dataclass
class DataObj:
    """ DataObj creates an object for each record in data
    """
    name: str
    profit: int
    space: float

I have another container class that holds the objects of above class

class DataContainer:
    """ Data Container class holding objects of DataObj class
    """
    def __init__(self, data_tuple_list: List[Tuple[str, int, float]]) -> None:
        self.container = []
        for data_tuple in data_tuple_list:
            self.container.append(DataObj(*data_tuple))

    def __getitem__(self, n: int) -> Type[DataObj]:
        return self.container.__getitem__(n)

However, when I check the code using mypy, I get following error

error: Incompatible return value type (got "DataObj", expected "Type[DataObj]")
Found 1 error in 1 file (checked 1 source file)

My python version is 3.8.10.

Question: How to fix the error.

EDIT

  1. If I use self.container: List[DataObj] = [], I get error: Incompatible return value type (got "DataObj", expected "Type[DataObj]") Found 1 error in 1 file (checked 1 source file)
  2. If I use self.container: List[Type[DataObj]] = [], I get error: Argument 1 to "append" of "list" has incompatible type "DataObj"; expected "Type[DataObj]" Found 1 error in 1 file (checked 1 source file).
Asked By: Lawhatre

||

Answers:

It’s possible that you didn’t type hint your container as well (self.container) so mypy looks at it as a List[Any] and probably can’t see that it only contains values of type DataObj so when you return something from the list, mypy can’t be sure that it’s something of type DataObj

Try:


class DataContainer:
    """ Data Container class holding objects of DataObj class
    """
    def __init__(self, data_tuple_list: List[Tuple[str, int, float]]) -> None:
        self.container: List[DataObj] = [
            DataObj(*data_tuple)
            for data_tuple in data_tuple_list
        ]

    def __getitem__(self, n: int) -> Type[DataObj]:
        return self.container[n]

EDIT

This is what I’ve tried and it worked for me:

from dataclasses import dataclass
from typing import List, Tuple


@dataclass
class DataObj:
    """ DataObj creates an object for each record in data
    """
    name: str
    profit: int
    space: float


class DataContainer:
    """ Data Container class holding objects of DataObj class
    """

    def __init__(self, data_tuple_list: List[Tuple[str, int, float]]) -> None:
        self.container = [
            DataObj(*data_tuple)
            for data_tuple in data_tuple_list
        ]

    def __getitem__(self, n: int) -> DataObj:
        return self.container[n]

if __name__ == '__main__':
    data_tuple_list_concrete = [
        ('test1', 1, 1.1),
        ('test2', 2, 2.2),
        ('test3', 3, 3.3),
        ('test4', 4, 4.4),
        ('test5', 5, 5.5),
    ]

    dc = DataContainer(data_tuple_list_concrete)
    print(dc[0])
    print(dc[1])
    print(dc[2])
    print(dc[3])
    print(dc[4])

"""
Output:

DataObj(name='test1', profit=1, space=1.1)
DataObj(name='test2', profit=2, space=2.2)
DataObj(name='test3', profit=3, space=3.3)
DataObj(name='test4', profit=4, space=4.4)
DataObj(name='test5', profit=5, space=5.5)
"""
$ mypy main.py
Success: no issues found in 1 source file
Answered By: David