Python Typing:根据函数参数声明返回值类型 [英] Python Typing: declare return value type based on function argument

查看:30
本文介绍了Python Typing:根据函数参数声明返回值类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

<小时>

这个答案建议使用TypeVar:

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(来自 typingtyping_extensions).

If a more complex signature, e.g. with keyword arguments, is needed, use Protocol (from typing or typing_extensions).

请注意,如果明确只想将 42 传递给 CallableLiteral(来自 typingtyping_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆