假设我有一个将类型作为参数并返回该类型实例的函数:
def fun(t):
return t(42)
然后,我可以调用它并获取提供的类型的对象:
fun(int) # 42
fun(float) # 42.0
fun(complex) # (42+0j)
fun(str) # "42"
fun(MyCustomType) # something
该列表并不详尽,我希望能够在适当的构造函数中使用任何类型。
然后,我想为该函数添加类型提示。该函数返回值的类型提示应该是什么?
我已经尝试过using simply
t
,因为t
是一种类型:def fun(t: type) -> t:
return t(42)
但这不起作用:
main.py:1: error: Name 't' is not defined
This answer建议using a
TypeVar
:from typing import TypeVar
T = TypeVar("T")
def fun(t: T) -> T:
return t(42)
但这似乎是不对的,因为
T
表示一种类型,因此它表明该类型本身是返回的,而不是其实例。 Mypy拒绝了它:main.py:6: error: "object" not callable
Using
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]
。
关于Python键入: declare return value type based on function argument,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60202691/