python - 有没有更好的方法来使用 Python 的类型模块为复合类型创建类型别名?
问题描述
我有一个带有一个参数的函数,它应该接受一个int
或一个None
作为参数。有几种方法可以为这种复合类型创建类型别名:
# test.py
import typing
IntOrNone_1 = typing.TypeVar('IntOrNone_1', int, None)
IntOrNone_2 = typing.Union[int, None]
def my_func1(xyz: IntOrNone_1):
return xyz
def my_func2(xyz: IntOrNone_2):
return xyz
my_func1(12)
my_func1(None)
my_func1(13.7)
my_func1('str')
my_func2(12)
my_func2(None)
my_func2(13.7)
my_func2('str')
这两种方法都按照我的预期做,但是,对应的mypy
错误略有不同,但基本上具有相同的含义。
test.py:14:错误:“my_func1”的类型变量“IntOrNone_1”的值不能是“float”
test.py:15:错误:“my_func1”的类型变量“IntOrNone_1”的值不能是“str”
test.py:19:错误:“my_func2”的参数 1 具有不兼容的类型“float”;预期“可选[int]”
test.py:20:错误:“my_func2”的参数 1 具有不兼容的类型“str”;预期“可选[int]”
我倾向于使用第二种方法,因为它还会报告导致错误的参数。
正如我所想的那样,这两种方法确实是等效的,还是其中一种方法更受欢迎?
解决方案
这两种方法远非等效。您应该避免将 TypeVars 视为仅仅是别名——相反,它们是您想要使您的函数泛型时使用的更特殊的形式。
用一个例子来解释什么是“通用函数”是最容易的。假设您要编写一个函数,该函数接受某个对象(任何对象!)并返回另一个完全相同类型的对象。你会怎么做?
我们可以做的一种方法是尝试使用object
:
def identity(x: object) -> object:
return x
这让我们接近了,因为我们的identity
函数至少可以接受任何字面意思(因为所有类型都继承自object
Python)。然而,这个解决方案是有缺陷的:如果我们传入一个 int ,我们就会返回 out object
,这不是我们想要的。
相反,我们需要的是一种让类型检查器了解这两种类型之间存在“关系”的方法。这正是TypeVar
派上用场的地方:
T = TypeVar('T')
def identity(x: T) -> T:
return x
在这种情况下,我们的 TypeVar 'T' 充当“占位符”,可以绑定到我们想要的任何类型。因此,如果我们这样做identity(3)
,T
则将被绑定到int
——因此类型检查器将因此理解返回类型也必须是int
!
如果我们T
在参数类型提示中多次使用,类型检查器将确保每次类型都相同。
那么,下面的表达式在做什么呢?
IntOrNone_1 = typing.TypeVar('IntOrNone_1', int, None)
好吧,事实证明,向我们的特殊占位符类型添加约束有时会很有用。例如,您已经进行了约束IntOrNone_1
,使其只能绑定到int
or None
,而不能绑定到其他类型。
最后,回答您的最后一个问题:在您给出的示例中,您绝对应该使用 Union,而不是 TypeVars。
是否使用 Union 或 Union 的类型别名实际上是个人喜好问题,但如果您不需要这种“占位符”或“通用”行为,则不应该使用 TypeVars。
如果您想了解有关如何使用 TypeVars 的更多信息,mypy 文档中有一个关于泛型的部分。它涵盖了我跳过的几件事,包括如何制作泛型类(不仅仅是泛型函数)。
推荐阅读
- javascript - 使用纯javascript显示营业时间的打开/关闭?
- javascript - 如何从数组中添加累积值
- angularjs - 如何在 AndularJs 1.5+ 和 ui-router 中使用 oclazyload 延迟加载打字稿模块?
- arrays - Vue 旧阵列镜像新阵列
- python - 合并两个列表并合并双精度值的最佳方法?
- java - 在 Eclipse 中创建包
- python-3.x - 从 s3 读取文件时 joblib.load 出错
- pyspark - 如何创建 EMR 集群 AWS Glue 数据目录设置?
- node.js - TypeError:无法读取未定义 React Express 的属性“原型”
- sql - SQL - 从一个表中查找存在于另一个表中的记录,如果不存在则删除