【问题标题】:typing: TypeVar vs. Union, mypy error: Missing type parameters for generic type [duplicate]键入:TypeVar 与 Union,mypy 错误:缺少泛型类型的类型参数 [重复]
【发布时间】:2021-08-07 19:28:36
【问题描述】:

尽管在typing documentationmypy documentationPEP 483 上花费了大量时间,但我仍在努力理解何时使用TypeVar 以及何时使用Union。

问题的简单版本:Numeric = TypeVar('Numeric', int, float)Numeric = Union[int, float] 有什么区别?

这是我遇到的更详细的示例:

"""example1.py
Use of Union to define "Numeric" type.
"""

from typing import Union, Sequence

Numeric = Union[int, float]

Vector = Sequence[Numeric]

Matrix = Sequence[Vector]

检查 mypy:

$ mypy --strict example1.py
Success: no issues found in 1 source file 

改用TypeVar

"""example2.py
Use of TypeVar to define "Numeric" type.
"""

from typing import TypeVar, Sequence

Numeric = TypeVar('Numeric', int, float)

Vector = Sequence[Numeric]

Matrix = Sequence[Vector]

检查 mypy:

$ mypy --strict example2.py
example2.py:11: error: Missing type parameters for generic type "Vector"
Found 1 error in 1 file (checked 1 source file)

上面的mypy错误是指Matrix的定义。为什么mypyexample1.py 满意,但对example2.py 不满意?

我可以通过将最后一行更改为Matrix = Sequence[Vector[Numeric]] 来消除example2.py 中的错误。

版本信息:

$ python --version
Python 3.8.4
$ mypy --version
mypy 0.782

【问题讨论】:

  • 我不确定错误本身。通常,TypeVarintfloat 中的一个的占位符,但在您实际提供基于它的值之前,该选择不会固定。也就是说,Matrix 可以包含所有int 值,或所有float 值,但不能同时包含每个值。使用Union,单个Matrix 的每个元素都可以是intfloat,与其他元素的类型无关。

标签: python python-3.x type-hinting mypy python-typing


【解决方案1】:

TypeVar 用于创建泛型类型。

Numeric = TypeVar('Numeric', int, float)

Vector = Sequence[Numeric]

... 表示Vector[T]Sequence[T] 的别名,其约束条件为issubclass(T, (int, float))。这意味着 mypy 认为 Vector 是一个不完整的类型,它会询问:“什么的向量?”,您可以写 Vector[Numeric] 来表示:“任何数字的向量”。

常用于函数或类,像这样:

T = TypeVar('T')
V = TypeVar('V')
def map(f: Callable[[T], V], it: Iterable[T]) -> Iterator[V]:
    for x in it:
        yield f(x)

这意味着即使您不确切知道要获得什么类型,也可以使事情成为类型安全的。

【讨论】:

  • 虽然TypeVarUnion 有不同的用例,但这个答案并不能解释为什么example2.py 可以按原来的方式修复。
  • 我想我应该更明确一点,是的。你认为我的编辑正确地解释了它吗?
  • 好的,是的。我认为我的困惑在于认为Sequence 比实际简单。
  • 感谢您的回答。我仍然不明白为什么声明 Vector = Sequence[Numeric] 会导致“不完整类型”,因为我已经指定它应该是一个数字序列。我的(也许是天真的)目标是将Vector 定义为由ints 和/或floats 组成的任何序列。我希望Matrix 只是Vectors 的序列。最后,我想注释def dot_product(v1: Vector, v2: Vector) 之类的函数。然后,在dot_product 中,我知道v1v2 的每个元素要么是ints,要么是floats。对于这个用例,我会使用Union 来定义Numeric吗?
  • 是的,您可以使用UnionTypeVar 用于 generic 类型,当你想像 Vector[T] 一样使用它时,我不知道如何解释得更清楚。
猜你喜欢
  • 1970-01-01
  • 2022-01-21
  • 2021-10-18
  • 2018-03-28
  • 2012-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-03
相关资源
最近更新 更多