假设我有一个函数将类型作为参数并返回该类型的实例:
def fun(t):
return t(42)
然后我可以调用它并获取提供类型的对象:
fun(int) # 42
fun(float) # 42.0
fun(complex) # (42+0j)
fun(str) # "42"
fun(MyCustomType) # something
该列表并不详尽,我希望能够使用任何具有适当构造函数的类型。
然后,我想为该函数添加类型提示。该函数的返回值的类型提示应该是什么?
我尝试过简单地使用
t
,因为t
是一种类型:
def fun(t: type) -> t:
return t(42)
但这不起作用:
main.py:1:错误:名称“t”未定义
TypeVar
:
from typing import TypeVar
T = TypeVar("T")
def fun(t: T) -> T:
return t(42)
但这似乎不对,因为
T
表示类型,因此它表明返回类型本身,而不是其实例。 Mypy 拒绝它:
main.py:6:错误:“对象”不可调用
Any
显然可以工作,但我觉得它太模糊了,它没有传达意图:
from typing import Any
def fun(t: type) -> Any:
return t(42)
TLDR:您需要一个
TypeVar
来表示调用的返回类型t
:
def fun(t: Callable[[int], R]) -> R:
...
Callable
,并且函数的返回类型是 Callable
的类型。这可以使用 TypeVar
作为返回类型来指定:
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*'
这也适用于类型,因为类型实例化是一个调用。
Protocol
(来自 typing
或 typing_extensions
)。
请注意,如果明确希望仅将
42
传递给 Callable
,则可以使用 Literal
(来自 typing
或 typing_extensions
)来指定。
R = TypeVar('R')
def fun(t: Callable[[Literal[42]], R]) -> R:
return t(42)
请注意,
Callable[[int], R]
类型的任何函数也满足Callable[[Literal[42]], R]
。
您正在寻找
typing.Type
,所以效果如下:
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)
注意,您的类型变量需要受到约束,因为并非所有
Type
对象都接受参数,但您可以将其限制为与您的示例类似的少数对象。
上面你已经有了答案,但我再重复一遍:
def fun(t: type[T]) -> T:
return t(42)
我认为
type
可以从Python 3.10开始使用。之前是Type
。
您可能想要这样的东西(将任何值转换为给定类型):
def fun(t: type[T], v) -> T:
return t(v)