Reputation: 3673
I want to add typing to a Python function that takes in a type as an argument (actually, a subtype of a specific class), and return an instance of that type. Think a factory that takes in the specific type as an argument, e.g.:
T = TypeVar('T', bound=Animal)
def make_animal(animal_type: Type[T]) -> T: # <-- what should `Type[T]` be?
return animal_type()
(obviously this is a very simplistic example, but it demonstrates the case)
This feels like something that should be possible, but I couldn't find how to properly type-hint this.
Upvotes: 11
Views: 5877
Reputation: 89472
Since Python 3.12, generic function declarations can be simplified with type parameter lists, which obviates the need to explicitly define TypeVar
s. (Also note that typing.Type
was deprecated in Python 3.9 in favor of directly subscripting type
.)
def make_animal[T](animal_type: type[T]) -> T:
return animal_type()
Upvotes: 2
Reputation: 3
You cast objects with typing.cast
from typing import TypeVar, cast
T = TypeVar("T", str, dict)
def my_function(expected_type: type[T]) -> T:
if expected_type is str:
return cast(T, "hi")
else:
return cast(T, {"message": "hi"})
This is useful if your situation requires dynamic typing that you cannot verify through Python's static typing system.
Upvotes: 0
Reputation: 3224
Not sure what your question is, the code you posted is perfectly valid Python code. There is typing.Type
that does exactly what you want:
from typing import Type, TypeVar
class Animal: ...
class Snake(Animal): ...
T = TypeVar('T', bound=Animal)
def make_animal(animal_type: Type[T]) -> T:
return animal_type()
reveal_type(make_animal(Animal)) # Revealed type is 'main.Animal*'
reveal_type(make_animal(Snake)) # Revealed type is 'main.Snake*'
See mypy output on mypy-play.
Upvotes: 13
Reputation: 2085
How about something like this?
from __future__ import annotations
from typing import Type
class Animal:
...
def make_animal(animal_type: Type[Animal]) -> Animal:
return animal_type()
Upvotes: -2