Python类型:基于函数参数声明返回值类型

2024-04-24 06:29:13 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有一个函数,该函数将type作为参数并返回该类型的实例:

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是一种类型:

def fun(t: type) -> t:
    return t(42)

但这不起作用:

main.py:1: error: Name 't' is not defined


This answer建议using a ^{}

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 ^{}显然有效,但我觉得它太模糊,无法传达意图:

from typing import Any

def fun(t: type) -> Any:
    return t(42)

Tags: 实例函数frompytyping类型returnmain
2条回答

TLDR:callingt的返回类型需要一个TypeVar

def fun(t: Callable[[int], R]) -> R:
    ...

在这里,对类型的约束过于严格。函数接受任何接受整数的^{},函数的返回类型为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*'

这也适用于类型,因为类型实例化是一个调用

如果需要更复杂的签名,例如带有关键字参数的签名,请使用^{}(从typingtyping_extensions


请注意,如果显式地只想将42传递给Callable,则可以使用^{}(来自typingtyping_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对象都接受参数,但您可以将其约束为一些与示例类似的对象

相关问题 更多 >