Home > Enterprise >  Python3: Type Hint, How to use TypeVar while defining a class whithing a Generic class
Python3: Type Hint, How to use TypeVar while defining a class whithing a Generic class

Time:09-23

I am trying to use the TypeVar T inside Generic class: in a _dataclass_helper

MyPy error in the "value"

from typing import Generic, TypeVar
from dataclasses import dataclass


_T = TypeVar("_T")


class Base(Generic[_T]):
    @dataclass
    class _dataclass_helper:
        value: _T  #<<--- mypy: Type variable "HW.DC_ValueGeneric._T" is unbound 
        string: str

    def __init__(self):
        pass

    # using _dataclass_helper in the code

I have tried to have _dataclass_helper as Generic, or either to define the _dataclass_helper outside the scope of Base... But both miss the target

CodePudding user response:

Let inner classes inherit Generic instead of outer classes:

class Base:
    @dataclass
    class _dataclass_helper(Generic[_T]):
        value: _T
        string: str

    def __init__(self):
        pass

According to your comments, what you want is to determine the generics of internal classes while determining the generics of external classes, but the internal class and the external class are two independent classes, and there is no connection between them. One possible option is to use a method to build instances of internal classes:

_T = TypeVar("_T")
_S = TypeVar("_S")


class Base(Generic[_T]):

    @dataclass
    class _dataclass_helper(Generic[_S]):
        value: _S
        string: str

    def __init__(self):
        pass
    
    def helper(self, value: _T, string: str) -> _dataclass_helper[_T]:
        return self._dataclass_helper(value, string)

CodePudding user response:

Found the answer in https://peps.python.org/pep-0484/#scoping-rules-for-type-variables

quoting

A generic class nested in another generic class cannot use same type variables. The scope of the type variables of the outer class doesn’t cover the inner one:

T = TypeVar('T')
S = TypeVar('S')

class Outer(Generic[T]):
    class Bad(Iterable[T]):       # Error
        ...
    class AlsoBad:
        x = None  # type: List[T] # Also an error

    class Inner(Iterable[S]):     # OK
        ...
    attr = None  # type: Inner[T] # Also OK
  • Related