0

I'm using this pattern often:

import typing


T = typing.TypeVar('T')
 
 
class Base(typing.Generic[T]):
    _type: typing.Type[T]
 
    def func(self) -> T:
        return self._type(42)
 
 
the_type: type = int
 
class A(Base[the_type]):
    _type = the_type
 
 
the_type = str
 
class B(Base[the_type]):
    _type = the_type

Is there any way to avoid passing the type to both Base[] and as _type?

I want something like this:

import typing


T = typing.TypeVar('T')
 
 
class Base(typing.Generic[T]):
    def func(self) -> T:
        return T(42)
 

class A(Base[int]):
    pass
 

class B(Base[str]):
    pass

but that's not how it works of course.

eepp
  • 7,255
  • 1
  • 38
  • 56
  • An *instance* of `Base` is what binds `T` to a particular type. You can't set the value of a class attribute using `T`. – chepner Jun 16 '23 at 20:02

1 Answers1

0

This is very similar to: https://stackoverflow.com/a/71720366/2952185

Here is how to apply these principles to your example (working code with no MyPy errors running strict mode):

from typing import Any, Generic, TypeVar, cast, get_args

T = TypeVar("T")


class Base(Generic[T]):
    def convert_type(self, original: Any) -> T:
        # We have to ignore the type here because we are accessing a
        # property that only exists for Generic types. MyPy doesn't
        # know that this is a Generic type, so it will complain.
        _type = get_args(type(self).__orig_bases__[0])[0]  # type: ignore
        return cast(T, _type(original))

    def func(self) -> T:
        value = 42
        return self.convert_type(value)


class A(Base[int]):
    pass


class B(Base[str]):
    pass


a = A()
value_a = a.func()
print(value_a, type(value_a))
b = B()
value_b = b.func()
print(value_b, type(value_b))
42 <class 'int'>
42 <class 'str'>
Gijs Wobben
  • 1,974
  • 1
  • 10
  • 13