Python:在Protocol和TypedDict之间共享类型注释

Python:在Protocol和TypedDict之间共享类型注释,python,typing,mypy,Python,Typing,Mypy,举个简单的例子: from\uuuuu future\uuuuu导入注释 输入类型为t 类别MyType: 定义初始化(self,s:str,i:int)->无: self.s=s self.i=i MyProto类(t.Protocol): s:str i:int MyDict类(t.TypedDict): s:str i:int def my_序列化程序(inst:MyProto)->MyDict: 返回{“s”:inst.s,“i”:inst.i} d=my_序列化程序(MyType(“a

举个简单的例子:

from\uuuuu future\uuuuu导入注释
输入类型为t
类别MyType:
定义初始化(self,s:str,i:int)->无:
self.s=s
self.i=i
MyProto类(t.Protocol):
s:str
i:int
MyDict类(t.TypedDict):
s:str
i:int
def my_序列化程序(inst:MyProto)->MyDict:
返回{“s”:inst.s,“i”:inst.i}
d=my_序列化程序(MyType(“a”,1))
所有类型检查都通过

现在,让我们假设
MyType
实际上是一个ORM类,它具有许多属性,这些属性是协议和dict类型的真实来源。每次向类添加属性时,必须在协议类主体和TypedAct类主体中维护相同的注释,这让人觉得有点多余

我想知道是否有一种方法可以集中定义类型注释,并告诉mypy这些是协议和dict类的类型定义

我试过这个:

类类型混合:
s:str
i:int
MyProto类(TypeMixin,t.Protocol):
通过
MyDict类(TypeMixin,t.TypedDict):
通过
然而,mypy抱怨:

test.py:15: error: All bases of a protocol must be protocols
test.py:19: error: All bases of a new TypedDict must be TypedDict types
。。。这实际上是运行时的一个类型错误

这是:

annos={“s”:“str”,“i”:“int”}
MyProto=type(“MyProto”,(t.Protocol,),{uuuuuu注释:annos})
MyDict=type(“MyDict”,(t.TypedDict,),{
def my_序列化程序(inst:MyProto)->MyDict:
返回{“s”:inst.s,“i”:inst.i}
这会运行,但mypy会抱怨,我认为这对mypy来说太过动态:

test.py:12: error: Argument 2 to "type" has incompatible type "Tuple[_SpecialForm]"; expected "Tuple[type, ...]"
test.py:13: error: Argument 2 to "type" has incompatible type "Tuple[object]"; expected "Tuple[type, ...]"
test.py:16: error: Variable "topsport.events.test.MyProto" is not valid as a type
test.py:16: error: Variable "topsport.events.test.MyDict" is not valid as a type
test.py:17: error: MyProto? has no attribute "s"
test.py:17: error: MyProto? has no attribute "i"

我想做的是不可能的吗?

出于好奇,你为什么需要一个类和一个TypedDict?在我看来,您实际上只需要类上的类型:反序列化的dict应该是短期的,所以让它成为type
dict[str,object]
通常就足够了。您还可以使用类似pydantic的东西来简化验证/反序列化/序列化。在任何情况下,如果确实需要这两种模式的类型,最好的办法可能是创建一个在构建时运行的脚本,以生成包含两种模式的文件。有点黑,但我认为没有其他方法可以做到这一点。
MyType
是我们业务的基础,每个应用程序都以某种能力与之交互。一些应用程序可以直接访问数据库,其他应用程序只能通过API获取数据,而那些应用程序通常不需要进行反序列化,因为使用dict表示就足够了。所以我只是希望每个用例的工具箱中都有一个类型定义。很容易编写一个单元测试,将每个单元中的注释与ORM列定义进行比较,所以我就这样做。谢谢@Michael0x2a。