Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending Generic.__class_getitem__ in Python to accept more params

How can one extend __class_getitem__ for a Python Generic class? I want to add arguments to __class_getitem__ while having some be propagated upwards to Generic.__class_getitem__.

Please see the below code snippet for an example use case (that doesn't run):

from typing import ClassVar, Generic, TypeVar

T = TypeVar("T")

class Foo(Generic[T]):
    cls_attr: ClassVar[int]

    def __class_getitem__(cls, cls_attr: int, item):
        cls.cls_attr = cls_attr
        return super().__class_getitem__(item)

    def __init__(self, arg: T):
        pass

foo = Foo[1, bool](arg=True)

Gives me this TypeError:

Traceback (most recent call last):
  File "/path/to/file.py", line 17, in <module>
    foo = Foo[1, bool](arg=True)
TypeError: Foo.__class_getitem__() missing 1 required positional argument: 'item'
like image 994
Intrastellar Explorer Avatar asked Oct 19 '25 20:10

Intrastellar Explorer


1 Answers

As @juanpa.arrivillaga suggests, this is the way to go:

from typing import ClassVar, Generic, TypeVar

T = TypeVar("T")

class Foo(Generic[T]):
    cls_attr: ClassVar[int]

    def __class_getitem__(cls, item: tuple[int, T]):
        cls.cls_attr = item[0]
        return super().__class_getitem__(item[1])

    def __init__(self, arg: T):
        self.arg = arg


foo = Foo[1, bool](arg=True)
assert foo.cls_attr == 1
assert foo.arg

Unfortunately, it looks like Python type inspection tooling is not advanced enough to understand this pattern. For example, mypy==0.971 (Sept 2022) doesn't support __class_getitem__ yet per https://github.com/python/mypy/issues/11501.

like image 104
Intrastellar Explorer Avatar answered Oct 21 '25 09:10

Intrastellar Explorer