python - 如何在不明确列出类型的情况下确保参数具有相同的类型?

标签 python type-hinting mypy python-typing

让我们假设我们需要一个函数,它接受任何类型的两个参数,只要两个参数具有相同的类型即可。您将如何使用 mypy 对其进行静态检查?

如果我们只需要函数接受一些有限数量的已知类型,这很容易:

from typing import TypeVar, List, Callable

T = TypeVar('T', int, str, List[int], Callable[[], int])

def f(a: T, b: T) -> None:
   pass

f(1, 2)
f("1", "2")
f([1], [2])
f(lambda: 1, lambda: 2)
f(1, "2") # mypy will print an error message

对于这段代码,mypy 可以确保 f 的参数是两个 int 或两个 str 或两个 int 或两个返回 int 的零参数函数。

但是如果我们事先不知道类型怎么办?如果我们需要类似于来自 F# 和 OCaml 的 let f (a:'t) (b:'t) = () 怎么办?简单地写 T = TypeVar('T') 会让 f(1, "2") 有效,这不是我们想要的。

最佳答案

你要求的是不可能的(见下文解释)。但通常情况下,python 中不需要要求两个参数具有完全相同的类型。

在您的示例中,intstrList[int]Callable[[]、int] 没有任何共同的方法或属性(除了任何两个 object 实例所具有的),所以除非你用 isinstance 手动检查类型,否则你不能真正用你的论点做任何你不能用 object 实例做的事情。你能解释一下你的用例吗?

为什么不能强制类型相等的解释

Mypy 类型系统有子类型。因此,当您编写 f(a, b) 时,mypy 仅检查 ab 的类型是否都是 T< 的子类型 而不是恰好等于 T

此外,mypy 子类型系统大多是预定义的,不受程序员控制,特别是每个类型都是 object 的子类型。 (IIUC,在 OCaml 中,程序员需要明确说明哪些类型应该处于子类型关系中,因此默认情况下每个类型约束都是相等约束。这就是为什么你可以在 OCaml 中做你想做的事)。

所以,当你写的时候

T = TypeVar('T')
f(a: T, b: T) -> None: ...
f(x, y)

您只是在告诉 mypy xy 的类型必须是某些常见类型 T 的子类型。当然,通过推断 Tobject,这个约束总是(简单地)得到满足。

更新

对于你在评论中的问题(是否可以确保 y 的类型是 x 类型的子类型?),答案也是否定的。

即使 mypy 允许一个类型变量从上面被指定的类型绑定(bind),这个绑定(bind)不能是另一个类型变量,所以这不会工作:

T = TypeVar('T')
U = TypeVar('U', bound=T, contravariant=True) # error, T not valid here
f(x: T, y: U) -> None

关于python - 如何在不明确列出类型的情况下确保参数具有相同的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40033093/

相关文章:

python - 客户端服务器通信opc ua

Python:如何覆盖子类中实例属性的类型提示?

python - 如何仅键入协议(protocol)方法的第一个位置参数并让其他参数不键入?

python - 为什么 mypy 拒绝我的 "mixed union"类型声明?

python - 如何获得 Numpy 矩阵的整数特征向量?

python - Pandas 标准偏差返回 NaN

子类的 Python 输入问题

python-3.x - Bytes-like object 或 Buffer 类型注解

python - 针对不同的Python版本使用模块

python - 在 PyCharm 中类型提示 dict.items() 时的奇怪行为