TypeVar('T',A,B)和TypeVar('T',bound = Union [A,B])之间的区别 [英] Difference between TypeVar('T', A, B) and TypeVar('T', bound=Union[A, B])

查看:497
本文介绍了TypeVar('T',A,B)和TypeVar('T',bound = Union [A,B])之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力理解以下两个TypeVar s

I'm struggling to get my head around the difference between the following two TypeVars

from typing import TypeVar, Union

class A: pass
class B: pass

T = TypeVar("T", A, B)
T = TypeVar("T", bound=Union[A, B])

有人想启发我吗?

一个我不明白的例子...

An example of something I don't get ...

T = TypeVar("T", bound=Union[A, B])

class AA(A): pass


class X(Generic[T]):
    pass


class XA(X[A]):
    pass


class XAA(X[AA]):
    pass

通过类型检查,但使用T = TypeVar("T", A, B)失败,

passes type checking, but with T = TypeVar("T", A, B) it fails with

generics.py:31:错误:"X"类型变量"T"的值不能为"AA"

generics.py:31: error: Value of type variable "T" of "X" cannot be "AA"

与一般问题有关:此问题有关Union[A, B]TypeVar("T", A, B)

Related to the general question: this question on the difference between Union[A, B] and TypeVar("T", A, B)

推荐答案

执行T = TypeVar("T", bound=Union[A, B])时,是说T可以绑定到Union[A, B]Union[A, B]的任何子类型. 边界上限.

When you do T = TypeVar("T", bound=Union[A, B]), you are saying T can be bound to either Union[A, B] or any subtype of Union[A, B]. It's upper-bounded to the union.

因此,例如,如果您具有类型为def f(x: T) -> T的函数,则传入以下任何类型的值都是合法的:

So for example, if you had a function of type def f(x: T) -> T, it would be legal to pass in values of any of the following types:

  1. Union[A, B](或A和B的任何子类型的并集,例如Union[A, BChild])
  2. A(或A的任何子类型)
  3. B(或B的任何子类型)
  1. Union[A, B] (or a union of any subtypes of A and B such as Union[A, BChild])
  2. A (or any subtype of A)
  3. B (or any subtype of B)

这是大多数编程语言中泛型的行为方式:它们使您可以施加一个上限.

This is how generics behave in most programming languages: they let you impose a single upper bound.

但是,当您执行T = TypeVar("T", A, B)时,您基本上是说T 必须要么是A的上限,要么是B的上限.也就是说,不是建立一个上限,您就可以建立多个!

But when you do T = TypeVar("T", A, B), you are basically saying T must be either upper-bounded by A or upper-bounded by B. That is, instead of establishing a single upper-bound, you get to establish multiple!

因此,这意味着将AB类型的值传递到f是合法的,但由于Union[A, B]联盟的上限既不是A也不是B.

So this means while it would be legal to pass in values of either types A or B into f, it would not be legal to pass in Union[A, B] since the union is neither upper-bounded by A nor B.

例如,假设您有一个可包含int或strs的可迭代对象.

So for example, suppose you had a iterable that could contain either ints or strs.

如果您希望此可迭代项包含int或str的任意混合,则只需一个Union[int, str]的单个上限.例如:

If you want this iterable to contain any arbitrary mixture of ints or strs, you only need a single upper-bound of a Union[int, str]. For example:

from typing import TypeVar, Union, List, Iterable

mix1: List[Union[int, str]] = [1, "a", 3]
mix2: List[Union[int, str]] = [4, "x", "y"]
all_ints = [1, 2, 3]
all_strs = ["a", "b", "c"]


T1 = TypeVar('T1', bound=Union[int, str])

def concat1(x: Iterable[T1], y: Iterable[T1]) -> List[T1]:
    out: List[T1] = []
    out.extend(x)
    out.extend(y)
    return out

# Type checks
a1 = concat1(mix1, mix2)

# Also type checks (though your type checker may need a hint to deduce
# you really do want a union)
a2: List[Union[int, str]] = concat1(all_ints, all_strs)

# Also type checks
a3 = concat1(all_strs, all_strs)

相反,如果要强制执行该函数将接受 all ints all strs 的列表,但不接受两者的混合,则需要多个上限.

In contrast, if you want to enforce that the function will accept either a list of all ints or all strs but never a mixture of either, you'll need multiple upper bounds.

T2 = TypeVar('T2', int, str)

def concat2(x: Iterable[T2], y: Iterable[T2]) -> List[T2]:
    out: List[T2] = []
    out.extend(x)
    out.extend(y)
    return out

# Does NOT type check
b1 = concat2(mix1, mix2)

# Also does NOT type check
b2 = concat2(all_ints, all_strs)

# But this type checks
b3 = concat2(all_ints, all_ints)

这篇关于TypeVar('T',A,B)和TypeVar('T',bound = Union [A,B])之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆