使用相同类型变量的类之间有关系吗?

问题描述 投票:0回答:1

typing.TypeVar
类允许指定可重用类型变量。使用 Python 3.12 / PEP 695,可以使用类型变量
A
定义一个类
B
/
T
,如下所示:

class A[T]:
    ...

class B[T]:
    ...

之前,使用 Python 3.11,你会这样做:

from typing import TypeVar, Generic

T = TypeVar("T")
class A(Generic[T]):
    ...

class B(Generic[T]):
    ...

对于第一个示例,

T
是在类范围中定义的,因此它们彼此不相关。 与第二个“旧”示例有什么区别吗?或者:两个类
A
B
之间有什么联系吗?

python mypy typing
1个回答
0
投票

从类型检查员的 POV 来看不存在这样的联系。

TypeVar
在类范围之外声明只是因为这样做很方便,并不意味着其用户之间有任何关系。

类型变量绑定在以下范围内:

  • 类作用域 - 如果一个类继承自
    Generic
    (或参数化
    Protocol
    ,或其他泛型类),则参数化其父类的类型变量将绑定到类作用域。此类型变量的所有出现都将解析为相同上下文中的相同类型。
  • 函数/方法作用域 - 如果函数包含类型变量作为其参数或返回类型的一部分,则该类型变量在函数体中解析为与签名中相同的类型。

没有其他绑定发生。

但是,可能存在清晰的语义关系(这是我反对 PEP695 的论点之一 - 不幸的是,我输掉了这场战斗)。考虑

django-stubs
(声明的永久链接):

# __set__ value type
_ST = TypeVar("_ST", contravariant=True)
# __get__ return type
_GT = TypeVar("_GT", covariant=True)

class Field(RegisterLookupMixin, Generic[_ST, _GT]):
    ... # omitted (there are 150+ lines here in fact)

class IntegerField(Field[_ST, _GT]):
    ...
class PositiveIntegerRelDbTypeMixin:
    ...
class SmallIntegerField(IntegerField[_ST, _GT]): ...
class BigIntegerField(IntegerField[_ST, _GT]):
    ...
class PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField[_ST, _GT]): ...
class PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, SmallIntegerField[_ST, _GT]): ...
class PositiveBigIntegerField(PositiveIntegerRelDbTypeMixin, BigIntegerField[_ST, _GT]): ...

显然,这些字段不必解析为相同类型的变量。然而,

_ST
_GT
具有语义,它们都是相同的。这不会影响类型检查,但会帮助那些阅读此代码的人。如果
_GT
_ST
是为每个类单独定义的,那么,除了不可读且令人不快的语法之外,我们还必须在每个类附近重复注释或记录模块文档字符串中的内容,并添加一个额外的查找步骤揭开它们的意义的神秘面纱。使用较长的形式,如
_SetterType
_GetterType
可以消除解释的需要,但也会使本来就很长的签名变得更长。此外,仍然有必要解释
Field
打字的工作原理(还有其他注意事项)。现在,它在 typevar 声明之后的文档字符串中进行了解释,但使用 PEP695 样式,它会被写得很远。

© www.soinside.com 2019 - 2024. All rights reserved.