首页 > 编程问答 >描述带有约束的通用协议的类型

描述带有约束的通用协议的类型

时间:2024-07-24 09:34:23浏览次数:14  
标签:python python-3.x generics python-typing typing

给定以下 python 代码:

from typing import Protocol, TypeVar


class A:
    pass


class B(A):
    pass

class C(A):
    pass


T = TypeVar("T", B, C, contravariant=True)


class X(Protocol[T]):

    def f(self, t: T) -> None:
        ...


class XTImpl(X[T]):

    def f(self, t: T) -> None:
        pass


class XBImpl(X[B]):

    def f(self, t: B) -> None:
        pass

如何键入一个仅接受 XTimpl 实例而不接受 XBImpl 实例的变量?

我真正的用例是我有函数


def fB(x: type[X[B]]):
    ...


def fC(x: type[X[C]]):
    ...


def fT(x):
    fB(x)
    fC(x)

并且我想在 fT

中键入参数 x X 例如,我想要类似

的东西(为此我收到错误“泛型类的预期类型参数”)。 T = TypeVar("T", B, C, contravariant=True) 如果我们将 T = TypeVar("T", A, contravariant=True) 更改为

那么我们可以只使用 X[A]。 但在我的真实用例中,B 和 C 不是共同祖先的直系子代。


遇到的问题源于类型提示和 Python 中结构类型系统的微妙之处。尽管 XBImpl 在技术上符合 X[T] 的要求(因为它可以处理 B 类型的输入,而 B T 的一个有效选项),但类型检查器无法推断出 fT 中的约束。

解决方法:使用类型界限

为了解决这个问题,我们可以引入另一个类型变量,该变量受限于 B C 的共同基类 A 。这使我们能够表达“接受 X 的任何实例,其中 T A 的子类型”的约束。

from typing import Protocol, TypeVar, Type

class A:
    pass

class B(A):
    pass

class C(A):
    pass

T = TypeVar("T", bound=A, contravariant=True)

class X(Protocol[T]):
    def f(self, t: T) -> None:
        ...

class XTImpl(X[T]):
    def f(self, t: T) -> None:
        pass

class XBImpl(X[B]):
    def f(self, t: B) -> None:
        pass

U = TypeVar("U", bound=A) 

def fB(x: Type[X[B]]):
    ...

def fC(x: Type[X[C]]):
    ...

def fT(x: Type[X[U]]) -> None:
    fB(x)
    fC(x)

fT(XTImpl) # 正确
fT(XBImpl) # 错误:参数 "x" 应该是 X[<类型变量 U>] 的子类型,与 X[B] 不兼容

在这个修改后的代码中:

  • 我们引入了新的类型变量 U ,它受限于 A
  • fT 的类型提示现在是 Type[X[U]] ,这意味着它接受 X 的任何类型,其中类型参数是 A 的子类型。

这种方法允许类型检查器识别 XBImpl 不满足 fT 的约束,因为它专门用于 B ,而不是任何 A 的子类型。

标签:python,python-3.x,generics,python-typing,typing
From: 78786101

相关文章

  • Python 检测 USB 设备 - IDLE 和 CMD 解释器之间的不同结果
    我正在尝试解决VDI解决方案中智能卡设备的USB重定向问题。我正在使用pyscard模块作为智能卡。对于进一步的上下文,主要问题是当浏览器插件调用用于处理智能卡的python脚本时,未检测到读卡器。关于问题,当我从CMD解释器运行此代码片段时,我收到空列表,表示系统上未找......
  • Python查找字符串的CRC32
    我尝试获取字符串数据类型变量的CRC32,但出现以下错误:>>>message='helloworld!'>>>importbinascii>>>binascii.crc32(message)Traceback(mostrecentcalllast):File"<stdin>",line1,in<module>TypeError:aby......
  • 使用python,如何创建重复的工作时间表
    这是我们公司的小组工作安排表。为三班制,2组日夜工作,1组休息。重复白天工作4天休息2天,然后再次夜间工作4天休息2天的时间表。我想使用python(pandas)自动安排在8月9日之后。抱歉英语不好,提前感谢您的帮助以下是使用Python和Pandas创建重复工作时间表的代码......
  • venv 已激活,但 pip 安装仍然默认进行,并且 python 在源代码中看不到该库
    在终端shell中的vscode中输入“whichpython”显示默认路径:C:\Users\erjan\AppData\Local\Programs\Python\Python311\python.exe(my_venv)但是(my_venv)意味着我的venv处于活动状态,我做了pipinstalltransformers,但下面的代码仍然显示错误-无法看到......
  • 在Python多处理中执行二进制信号量或互斥体以进行上下文切换操作
    我正在尝试自动化win应用程序和java应用程序之间的同步关系。我的标准是:启动win和jav应用程序在jav应用程序中执行命令等待jav应用程序的响应使用jav应用程序的响应到Windows应用程序作为输入。在jav应用程序中执行命令win应用程序......
  • 在spyder-python上随机出现的这些奇怪的亮点是什么
    在此处输入图像描述每次我单击此按钮或进行任何更改时,都会创建奇怪的突出显示,当我最小化功能时更是如此。有什么建议如何摆脱这些或可能的原因是什么?谢谢!我尝试更改外观首选项中的设置,但无法影响问题。很抱歉,我无法直接查看或与Spyder界面交互。我是一个AI......
  • 比较Python字典并找到缺失的元素
    我遇到了一个问题,我已经尝试了几天但没有得到任何结果。我想比较两个字典,在一个字典中有“赛前”足球比赛,在第二个字典中有“现场”足球比赛。我想将它们相互比较并打印它们(如果有)没有赛前比赛直播。示例1pre=[{"Home":"Genoa","Away":"In......
  • Python使用Visual Studio打印功能不显示输出
    任务:检查一个整数是正数还是负数。检查整数是否能被2整除。当输入0时,我需要退出循环并报告每个计数和总和。print函数没有显示任何输出。这是我从defmain()开始使用的代码defmain():countpositive=0countnegative=0count_divisible_by_2=0sump......
  • Python 中的像素最小二乘法
    我有一个非线性前向模型,它计算每个像素参数w的灰度图像。我还可以使用scipys优化函数来反转模型。我目前遇到的唯一问题是图像的大小使得这个解决方案非常慢...比如7%的像素在40分钟内计算得很慢。我使用for循环遍历所有像素并按像素应用模型。我尝试过......
  • SQL 命令在手动运行时工作正常(SQL Developer),但在 Python 的 oracledb 模块中给出 ORA-
    我正在使用OracleSQL数据库,并且我想运行该命令ALTERSESSIONSETNLS_DATE_FORMAT='YYYY-MM-DD';当我从SQLDeveloper应用程序手动运行它时,它工作正常。但是,当我使用oracledb模块从Python运行它时,出现以下错误:ErrorrunningSQLscript:ORA-00922:mi......