python - 找到正确的 Python 类型提示,例如,内置函数 map() 的签名
问题描述
描述
在 Python 3.5 或更高版本中,支持类型提示(有关更多信息,请参见此处)。但是,常见类型的正确用法没有得到很好的记录。
例如,从官方网站,我可以收集以下(正确的)用法:
细绳
# The function signature of greeting is: Callable[[str], str]
def greeting(name: str) -> str:
return 'Hello ' + name
整数
# The function signature of add is: Callable[[int, int], int]
def add(a: int, b: int) -> int:
return a + b
浮点数
# 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
列表
from typing import List, TypeVar
T = TypeVar('T')
def repeat(x: T, n: int) -> List[T]:
return [x] * n
元组
from typing import Tuple, TypeVar
T = TypeVar('T')
def double(x: T) -> Tuple[T, T]:
return (x, x)
问题
我的问题是:
1. 什么是返回类型map
?
from typing import Iterable
# Is this correct?
x: Iterable[float] = map(int.__float__, [1, 2, 3])
我不确定这是否是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]]
但实际上,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]]
一般来说,我想它应该像下面这样,但这不是正确的写法:
FunctionN = Callable[[T1, T2, ..., Tn], R]
typeOfMap = Callable[[FunctionN, Iterable[T1], Iterable[T2], ..., Iterable[Tn]], Iterable[R]]
那么,正确的写法是什么呢?
3. 一般来说,我在哪里可以找到 Python 函数/方法的正确类型提示,包括内置的,核心库中的那些?
我需要它们主要用于学习目的。
4. 有没有办法输出编译器/解释器计算出来的类型推断结果,比如Haskell或者Erlang?
我知道 Haskell 和 Erlang 是函数式编程语言,变量是不可变的,所以让这成为可能会容易得多,但万一 Python 也有类似的功能,我想知道。
5. 有什么方法可以检查我的类型提示是否正确?
或者至少让它在编译时/运行时向我显示一些警告/错误,以便我知道有问题。
参考
在撰写本文时,最新的稳定版本是 3.8.0。
解决方案
1. 什么是返回类型
map
?
map
的返回值当前键入为Iterator[T]
. 由于迭代器是可迭代的,因此您的注释x: Iterable[float] = map(int.__float__, [1, 2, 3])
是有效的。(另外,只需写map(float, [1, 2, 3])
.)
2.从更广泛的意义上说,map的‘函数签名’是什么?
目前无法表示,这就是为什么typeshed 具有最多 6 个泛型参数的重载。(一个相关问题)
3. 一般来说,我在哪里可以找到 Python 函数/方法的正确类型提示,包括内置的,核心库中的那些?
我需要它们主要用于学习目的。
Python 的类型库。请注意,出于非学习目的(练习),您通常应该让类型被推断或使用任何有意义的类型,而不是最精确的类型。
您也可以使用reveal_type
- 见下文。
4. 有没有办法输出编译器/解释器计算出来的类型推断结果,比如Haskell或者Erlang?
我知道 Haskell 和 Erlang 是函数式编程语言,变量是不可变的,所以让这成为可能会容易得多,但万一 Python 也有类似的功能,我想知道。
这取决于您的类型检查器。我的reveal_type
.
x = map(float, [1, 2, 3])
reveal_type(x) # note: Revealed type is 'typing.Iterator[builtins.float*]'
5. 有什么方法可以检查我的类型提示是否正确?
或者至少让它在编译时/运行时向我显示一些警告/错误,以便我知道有问题。
静态地,这就是类型检查。(例如,如果您的x
提示错误,Mypy 会告诉您。)它无法捕捉所有内容,尤其是在 Python 这样动态的语言中,但这就是编程的本质。
有一些项目基于类型注释执行某种级别的运行时断言,但我没有使用过或真正会费心。
推荐阅读
- android - Ionic2-Calendar 现在在设备上失败
- ajax - 等待 AJAX 调用未按预期工作
- python - “简单”聚类的最快方法?
- java - 如何在 Jenkins 中更改 JAR 构建路径?
- symfony4 - 使用断言验证重复条目 - Symfony/API-Platform
- node.js - 在 MongoDB 中查找某个坐标(纬度、经度)位于哪个多边形中?
- vtiger - 在 Vtiger 数据库中,我在哪里可以找到表 vtiger_users 和 vtiger_contactdetails 之间的关系?
- php - 如何循环发送ajax请求
- php - 在 DK PDF 模板中显示 WooCommerce 产品图像
- r - data.table 选择键不等于值的行