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

Sup*_*oot 11 python typing mypy

举个简单的例子:

from __future__ import annotations
import typing as t


class MyType:
    def __init__(self, s: str, i: int) -> None:
        self.s = s
        self.i = i


class MyProto(t.Protocol):
    s: str
    i: int


class MyDict(t.TypedDict):
    s: str
    i: int


def my_serializer(inst: MyProto) -> MyDict:
    return {"s": inst.s, "i": inst.i}


d = my_serializer(MyType("a", 1))
Run Code Online (Sandbox Code Playgroud)

所有类型检查均通过。

现在我们可以说这MyType实际上是一个具有许多属性的 ORM 类,它是协议和字典类型的真实来源。每次将属性添加到类中时,都必须在 Protocol 类主体和 TypedDict 类主体中维护相同的注释,这感觉有点多余。

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

我试过这个:

class TypeMixin:
    s: str
    i: int


class MyProto(TypeMixin, t.Protocol):
    pass


class MyDict(TypeMixin, t.TypedDict):
    pass
Run Code Online (Sandbox Code Playgroud)

然而,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
Run Code Online (Sandbox Code Playgroud)

...这实际上是运行时的类型错误。

和这个:

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
Run Code Online (Sandbox Code Playgroud)

这个运行,但 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"
Run Code Online (Sandbox Code Playgroud)

我想做的事情是不可能的吗?