找到合适的 Python 类型提示,例如内置函数 map() 的签名

Siu*_*ji- 5 python built-in type-hinting python-3.x

描述

在 Python 3.5 或更高版本中,支持类型提示(有关更多信息,请参见此处)。但是,常见类型的正确用法没有很好的文档记录。

例如,从官方网站,我可以收集以下(正确的)用法:

细绳

# The function signature of greeting is: Callable[[str], str]
def greeting(name: str) -> str:
    return 'Hello ' + name
Run Code Online (Sandbox Code Playgroud)

整数

# The function signature of add is: Callable[[int, int], int]
def add(a: int, b: int) -> int:
    return a + b
Run Code Online (Sandbox Code Playgroud)

浮点数

# The default value of x is 1.0
def reciprocal(x: float = 1.0) -> float:
    from math import nan
    if x == 0:
        return nan
    return 1 / x
Run Code Online (Sandbox Code Playgroud)

列表

from typing import List, TypeVar

T = TypeVar('T')

def repeat(x: T, n: int) -> List[T]:
    return [x] * n
Run Code Online (Sandbox Code Playgroud)

元组

from typing import Tuple, TypeVar

T = TypeVar('T')

def double(x: T) -> Tuple[T, T]:
    return (x, x)
Run Code Online (Sandbox Code Playgroud)

问题

我的问题是:

1. 的返回类型是map什么?

from typing import Iterable

# Is this correct?
x: Iterable[float] = map(int.__float__, [1, 2, 3])
Run Code Online (Sandbox Code Playgroud)

我不确定这是否是上述的正确类型提示x

2. 从广义上讲,什么是 的“函数签名” map

from typing import Callable, Iterable, TypeVar

T = TypeVar('T')
U = TypeVar('U')

# In the above usage, the type of the map function seems to be:
Function1 = Callable[[T], U]
typeOfMap = Callable[[Function1, Iterable[T]], Iterable[U]]

# Or in one line:
typeOfMap = Callable[[Callable[[T], U], Iterable[T]], Iterable[U]]
Run Code Online (Sandbox Code Playgroud)

但实际上,map 函数可以接受多个迭代。它被记录为:

map(function, iterable, ...)

它可以像这样使用:

# The result is: [['A'], ['B', 'B'], ['C', 'C', 'C']]
result = list(map(repeat, ['A', 'B', 'C'], [1, 2, 3]))

T1 = TypeVar('T1')
T2 = TypeVar('T2')
R = TypeVar('R')

# So, the type of map function in this usage seems to be:
Function2 = Callable[[T1, T2], R]
typeOfMap = Callable[[Function2, Iterable[T1], Iterable[T2]], Iterable[R]]
Run Code Online (Sandbox Code Playgroud)

一般来说,我想它应该像下面这样,但这不是正确的写法:

FunctionN = Callable[[T1, T2, ..., Tn], R]
typeOfMap = Callable[[FunctionN, Iterable[T1], Iterable[T2], ..., Iterable[Tn]], Iterable[R]]
Run Code Online (Sandbox Code Playgroud)

那么,正确的写法是怎样的呢?

3. 一般来说,我在哪里可以找到 Python 函数/方法的正确类型提示,包括内置的,核心库中的?

我需要它们主要是为了学习目的。

4. 有没有办法输出编译器/解释器计算出的类型推断结果,比如Haskell或者Erlang?

我知道 Haskell 和 Erlang 是函数式编程语言,并且变量是不可变的,所以让这成为可能要容易得多,但以防万一,如果 Python 也有类似的功能,我想知道。

5. 有什么办法可以检查我的类型提示是否正确?

或者至少让它在编译时/运行时向我显示一些警告/错误,以便我知道出现问题。

参考

在撰写本文时,最新的稳定版本是 3.8.0。

Ry-*_*Ry- 7

\n

1. 的返回类型是什么map

\n
\n\n

map\xe2\x80\x99s 返回值当前键入为Iterator[T]. 由于迭代器是可迭代的,因此您的注释x: Iterable[float] = map(int.__float__, [1, 2, 3])是有效的。(另外,只写map(float, [1, 2, 3])。)

\n\n
\n

2. 从更广泛的意义上讲,map的“函数签名”是什么?

\n
\n\n

目前无法表示它\xe2\x80\x99,这就是为什么typeshed 具有最多 6 个泛型参数的重载。(一个相关问题

\n\n
\n

3. 一般来说,我在哪里可以找到Python函数/方法的正确类型提示,包括内置函数/方法,以及核心库中的函数/方法?

\n\n

我需要它们主要是为了学习目的。

\n
\n\n

Python\xe2\x80\x99s typeshed 存储库。请注意,出于学习目的 \xe2\x80\x93 练习 \xe2\x80\x93 您通常应该让类型被推断或使用任何有意义的类型而不是最精确的类型。

\n\n

您还可以使用reveal_type\xe2\x80\x93 ,如下所示。

\n\n
\n

4. 有没有办法输出编译器/解释器计算出的类型推断结果,如Haskell或Erlang?

\n\n

我知道 Haskell 和 Erlang 是函数式编程语言,变量是不可变的,所以实现这一点会容易得多,但以防万一 Python 也有类似的功能,我想知道。

\n
\n\n

这取决于您的类型检查器。迈皮有reveal_type.

\n\n
x = map(float, [1, 2, 3])\nreveal_type(x)  # note: Revealed type is \'typing.Iterator[builtins.float*]\'\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

5. 有什么方法可以检查我的类型提示是否正确?

\n\n

或者至少让它在编译时/运行时向我显示一些警告/错误,以便我意识到出了问题。

\n
\n\n

静态地讲,\xe2\x80\x99 就是类型检查。(例如,如果您的x提示错误,Mypy 会告诉您。)它不能捕获所有内容,尤其是在像 Python 这样动态的语言中,但这就是编程的本质。

\n\n

有一些项目基于类型注释进行某种程度的运行时断言,但我\xe2\x80\x99都没有使用过或真正会打扰。

\n