Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在python中使用TypeVar输入和输出多个通用协议?_Python_Python Typing - Fatal编程技术网

如何在python中使用TypeVar输入和输出多个通用协议?

如何在python中使用TypeVar输入和输出多个通用协议?,python,python-typing,Python,Python Typing,我希望使用多个通用协议并确保它们兼容: 从输入import-TypeVar、Protocol、Generic 从数据类导入数据类 #检查失败,如下所示,且逆变=真或协变=真: A=类型变量(“A”) C类(协议[A]): def f(自身,a:a)->无:通过 D类(协议[A]): def g(自身)->A:通过 #只是演示我的用例;没有错误: @数据类 类兼容项(泛型[A]): c:c[A] d:d[A] Mypy给出了以下错误: Invariant type variable 'A' us

我希望使用多个通用协议并确保它们兼容:

从输入import-TypeVar、Protocol、Generic
从数据类导入数据类
#检查失败,如下所示,且逆变=真或协变=真:
A=类型变量(“A”)
C类(协议[A]):
def f(自身,a:a)->无:通过
D类(协议[A]):
def g(自身)->A:通过
#只是演示我的用例;没有错误:
@数据类
类兼容项(泛型[A]):
c:c[A]
d:d[A]
Mypy给出了以下错误:

Invariant type variable 'A' used in protocol where contravariant one is expected
Invariant type variable 'A' used in protocol where covariant one is expected

我知道这可以通过创建
C
D
通用ABC类来实现,但我想使用协议。

简单的解释是,您的方法破坏了子类型的传递性;有关更多信息,请参阅。它非常清楚地解释了为什么您的
D
协议(以及隐含的
C
协议)会遇到这个问题,以及为什么每个协议都需要不同类型的差异来解决这个问题。您还可以查找有关类型差异的信息

解决方法是:使用协变和逆变协议,但要使泛型数据类保持不变。这里最大的障碍是继承,为了使用协议,您必须处理继承,但这与您的目标有点相切。我将在这里切换命名以突出显示起作用的继承性,这就是本文的全部内容:

A=TypeVar(“A”)#不变类型
A_cov=TypeVar(“A_cov”,协变=True)#协变类型
A_contra=TypeVar(“A_contra”,contravariant=True)#逆变类型
#使其相反
班级录取(协议[相反]):
def(self,a:a_contra)->无:通过
#给出输出的协方差
类输出(协议[A_cov]):
def g(自我)->A_cov:通过
#只需告诉IntakeOutput类型需要相同即可
#既然a是不变的,它就不在乎了
#输入和输出需要反向/协方差
@数据类
类输入输出(通用[A]):
取录:取录[A]
输出:输出[A]
您可以看到,这适用于以下测试:

类动物:
...
类别猫(动物):
...
犬类(动物):
...
进口类别:
def f(自身,a:Cat)->无:通过
等级:进口狗:
def f(自身,a:狗)->无:通过
类输出cat:
def g(自身)->类别:通过
类输出狗:
def g(自身)->狗:通过
compat_cat:IntakeOutput[cat]=IntakeOutput(intakecot(),OutputCat())
compat_dog:IntakeOutput[dog]=IntakeOutput(IntakeDog(),OutputDog())
#这会在mypy中出错
compat_fail:IntakeOutput[Dog]=IntakeOutput(IntakeDog(),OutputCat())
这会产生以下错误:

Invariant type variable 'A' used in protocol where contravariant one is expected
Invariant type variable 'A' used in protocol where covariant one is expected
main.py:48:错误:“IntakeOutput”的参数2具有不兼容的类型“OutputCat”;预期的“输出[狗]”
main.py:48:注意:“OutputCat”的以下成员存在冲突:
main.py:48:注:预计:
main.py:48:注:def g(self)->Dog
main.py:48:note:get:
main.py:48:注:def g(自)->Cat
有什么问题吗?你放弃了什么?即,
IntakeOutput
中的继承。以下是您不能做的事情:

类摄入动物:
def f(自身,a:动物)->无:通过
输出级:
def g(自我)->动物:通过
#好的,正如所料
ok1:摄入输出[动物]=摄入输出(摄入动物(),输出动物())
#好的,因为输出是协变的
ok2:IntakeOutput[动物]=摄入输出(IntakeAnimal(),OutputDog())
#两者都失败了,因为摄入是相反的
故障1:输入输出[动物]=输入输出(输入狗(),输出狗())
故障2:输入输出[动物]=输入输出(输入狗(),输出动物())
#好的,因为摄入是反向的
ok3:IntakeOutput[Dog]=IntakeOutput(IntakeAnimal(),OutputDog())
#这失败了,因为输出是协变的
故障3:吸入输出[狗]=吸入输出(吸入动物(),输出动物())
故障4:IntakeOutput[Dog]=IntakeOutput(IntakeDog(),OutputImal())

所以。就在那里。你可以继续玩这个。

什么不起作用?