Suppose I have function that takes type as argument and returns instance of that type:
def fun(t):
return t(42)
Then I can call it and get objects of provided types:
fun(int) # 42
fun(float) # 42.0
fun(complex) # (42+0j)
fun(str) # "42"
fun(MyCustomType) # something
That list is not exhaustive, I'd like to be able to use any type with appropriate constructor.
Then, I'd like to add type hints for that function. What should be the type hint for return value of that function?
I've tried using simply t
, as t
is a type:
def fun(t: type) -> t:
return t(42)
but that doesn't work:
main.py:1: error: Name 't' is not defined
This answer suggests using a TypeVar
:
from typing import TypeVar
T = TypeVar("T")
def fun(t: T) -> T:
return t(42)
But that doesn't seem to be right, as T
denotes a type, so it suggests that type itself is returned, not its instance. Mypy rejects it:
main.py:6: error: "object" not callable
Using Any
obviously work, but I feel it's too vague, it doesn't convey the intent:
from typing import Any
def fun(t: type) -> Any:
return t(42)
The Python return statement is a special statement that you can use inside a function or method to send the function's result back to the caller. A return statement consists of the return keyword followed by an optional return value. The return value of a Python function can be any Python object.
type() method returns class type of the argument(object) passed as parameter in Python.
Python type() is a built-in function that returns the type of the objects/data elements stored in any data type or returns a new type object depending on the arguments passed to the function. The Python type() function prints what type of data structures are used to store the data elements in a program.
The Python runtime does not enforce function and variable type annotations. They can be used by third party tools such as type checkers, IDEs, linters, etc. This module provides runtime support for type hints. The most fundamental support consists of the types Any , Union , Callable , TypeVar , and Generic .
TLDR: You need a TypeVar
for the return type of calling t
:
def fun(t: Callable[[int], R]) -> R:
...
Constraining on a type is too restrictive here. The function accepts any Callable
that takes an integer, and the return type of the function is that of the Callable
. This can be specified using a TypeVar
for the return type:
from typing import Callable, TypeVar
R = TypeVar('R') # the variable return type
def fun(t: Callable[[int], R]) -> R:
return t(42)
fun(int) # Revealed type is 'builtins.int*'
fun(float) # Revealed type is 'builtins.float*'
reveal_type(fun(lambda x: str(x))) # Revealed type is 'builtins.str*'
This works for types as well, because type instantiation is a call.
If a more complex signature, e.g. with keyword arguments, is needed, use Protocol
(from typing
or typing_extensions
).
Note that if one explicitly wants to pass only 42
to the Callable
, Literal
(from typing
or typing_extensions
) can be used to specify that.
R = TypeVar('R')
def fun(t: Callable[[Literal[42]], R]) -> R:
return t(42)
Note that any function of the type Callable[[int], R]
also satisfies Callable[[Literal[42]], R]
.
You are looking for typing.Type
, so something to the effect of:
from typing import TypeVar, Type
T = TypeVar("T", str, complex, float, int)
def fun(t: Type[T]) -> T:
return t(42)
fun(int)
fun(float)
fun(complex)
fun(str)
Note, your type variable needs to be constrained, because not all Type
objects accept arguments, but you can constrain it to a few that do like your example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With