Home > database >  How can I narrow the Generic type in python3?
How can I narrow the Generic type in python3?

Time:10-19

The Generic[T] allows any T, but I want the mypy errors out if the T is not subclass of some class. For example:

from enum import Enum
from typing import Dict, Generic, TypeVar

T = TypeVar("T")

class test_t(Generic[T]):
    data: T
    def __init__(self, data: T):
        self.data = data

... some magic code define GenericEnum ...

class test2_t(GenericEnum[T]):
    data: T
    def __init__(self, data: T):
        self.data = data

test_t[int](10) # this is fine
test2_t[int](10) # mypy should yield some error about the int is not compatible generic type

maybe I could subclass the Generic class and check the T with issubclass() during test_t[int]. But I do not know which method I should override, or if there is already some canonical way to do this

CodePudding user response:

Generic is only a helper to make classes generic over some Type variables. In order to limit what a Type variable accepts the specific TypeVar has to be bounded or constrained.

A bounded Type variable is limited to subclasses of the given type:

from typing import Generic, TypeVar

B = TypeVar("B", bound=str)

class test_b(Generic[B]):
    def __init__(self, data: S):
        self.data = data

test_b("yes!")
test_b[int]  # error: Value of type variable "B" of "test_b" cannot be "int"
test_b(12)   # error: Value of type variable "B" of "test_b" cannot be "int"

When matching a subclass of the bound, the Type Var is inhabited by the most specific subclass. For example, when matching class String(str) as a subclass of str then B is inhabited by String.

A constrained Type variable is limited to the given types:

from typing import Generic, TypeVar

C = TypeVar("C", str, list)

class test_c(Generic[C]):
    data: C
    def __init__(self, data: C):
        self.data = data

test_c("yes!")
test_c(["y", 1, True])
test_c[int]  #  Value of type variable "C" of "test_c" cannot be "int"
test_c(12)   #  Value of type variable "C" of "test_c" cannot be "int"

When matching a subclass of any constraint, the Type Var is inhabited by the respective constraint. For example, when matching class String(str) as a subclass of str then C is inhabited by str.

  • Related