Python Generic class of Matrix, I receive Cannot instantiate typing.TypeVar error

Viewed 368

I have written the following code. But I am receiving TypeError: Cannot instantiate typing.TypeVar

from typing import TypeVar, Generic, List, Tuple
T = TypeVar('T')


class MyInt:
    p: int

    def __init__(self, value: int):
        self.p = value


class Vector(Generic[T]):
    items: List[T]

    def __init__(self, sz: int):
        self.items = [T(0) for _ in range(sz)]

    def __init__(self, l: List[T]):
        self.items = l


class Matrix(Generic[T]):
    items: List[Vector[T]]

    def __init__(self, rw: int, cl: int):
        self.items = [Vector[T](cl) for _ in range(rw)]

    def __init__(self, sz: Tuple[int, int]):
        rw, cl = sz
        self.items = [Vector[T](cl) for _ in range(rw)]


myMatrix = Matrix[MyInt](1, 2)

I don't know how to create an instance of MyInt when I create an instance of Matrix[MyInt]. Can you help me in this?

1 Answers

There are two issues with your code that needs to be fixed:

First of all, you can not have function overloading in Python. Therefore, your multiple __init__ declarations will not work. As a workaround, you can define static methods that instantiate the class. I used method names like fill or fromList.

To fix the issue related to creating an instance of TypeVar, I used the trick to pass the default value of the matrix and vector as a parameter.

So to combine the above solutions, the matrix instatiation will be

myMatrix = Matrix[MyInt].fill(1,2, MyInt(0))

And class implementation looks like this:

class Vector(Generic[T]):
    items: List[T]

    def __init__(self):
        self.items = []

    @staticmethod
    def fill(sz: int, default: T):
        r = Vector[T]()
        r.items = [default for _ in range(sz)]
        return r

    @staticmethod
    def fromList(l: List[T]):
        r = Vector[T]()
        r.items = l
        return r


class Matrix(Generic[T]):
    items: List[Vector[T]]

    def __init__(self):
        self.items = []

    @staticmethod
    def fill(rw: int, cl:int, default:T):
        r = Matrix[T]()
        r.items = [Vector[T].fill(cl, default) for _ in range(rw)]
        return r

    @staticmethod
    def fill_size(sz: Tuple[int, int], default: T):
        rw, cl = sz
        return Matrix[T].fill(rw, cl, default)

Related