Python Typing:根据函数参数声明返回值类型 [英] Python Typing: declare return value type based on function argument
问题描述
假设我有一个将类型作为参数并返回该类型实例的函数:
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
该列表并不详尽,我希望能够使用具有适当构造函数的任何类型.
然后,我想为该函数添加类型提示.该函数返回值的类型提示应该是什么?
Then, I'd like to add type hints for that function. What should be the type hint for return value of that function?
我试过 简单地使用 t
,因为 t
是一种类型:
I've tried using simply t
, as t
is a type:
def fun(t: type) -> t:
return t(42)
但这不起作用:
main.py:1: 错误:名称 't' 未定义
main.py:1: error: Name 't' is not defined
<小时>
from typing import TypeVar
T = TypeVar("T")
def fun(t: T) -> T:
return t(42)
但这似乎不对,因为 T
表示一种类型,所以它表明返回的是类型本身,而不是它的实例.Mypy 拒绝它:
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: 错误:对象"不可调用
main.py:6: error: "object" not callable
<小时>
使用Any
显然有效,但我觉得它太模糊了,没有传达意图:
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)
推荐答案
TLDR: You need a TypeVar
用于调用的返回类型 t
:
TLDR: You need a TypeVar
for the return type of calling t
:
def fun(t: Callable[[int], R]) -> R:
...
<小时>
此处对类型的约束过于严格.该函数接受任何 Callable
接受一个整数,函数的返回类型是 Callable
的类型.这可以使用 TypeVar
作为返回类型来指定:
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.
如果一个更复杂的签名,例如需要关键字参数,使用 Protocol
(来自 typing
或 typing_extensions
).
If a more complex signature, e.g. with keyword arguments, is needed, use Protocol
(from typing
or typing_extensions
).
请注意,如果明确只想将 42
传递给 Callable
,Literal
(来自 typing
或 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)
请注意,Callable[[int], R]
类型的任何函数也满足 Callable[[Literal[42]], R]
.
Note that any function of the type Callable[[int], R]
also satisfies Callable[[Literal[42]], R]
.
这篇关于Python Typing:根据函数参数声明返回值类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!