微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Python:如何在 mixin 方法中指定函数返回类型

如何解决Python:如何在 mixin 方法中指定函数返回类型

我正在尝试准确注释 mixin 方法的返回类型。

下面的最小示例:

from dataclasses import dataclass,field
from typing import Dict,Protocol

class Hasstore(Protocol):
    store: dict


class StoreGetMixin:
    def __getitem__(self: Hasstore,key: str):  # what to put in -> type?
        return self.store[key]


@dataclass
class ThingOne:
    size: int


@dataclass
class ThingTwo:
    name: str


@dataclass
class Ones(StoreGetMixin):
    store: Dict[str,ThingOne] = field(default_factory=dict)


@dataclass
class Twos(StoreGetMixin):
    store: Dict[str,ThingTwo] = field(default_factory=dict)


ones = Ones()
ones.store = {"a": ThingOne(1),"b": ThingOne(2)}
one = ones["a"]  # <- this should be typed as a ThingOne

twos = Twos()
twos.store = {"a": ThingTwo("one"),"b": ThingTwo("two")}
two = twos["a"]  # <- this should be typed as a ThingTwo

所以我正在尝试编写一个可重用的 mixin,它可以访问各种数据类中的 store 字典。但我不知道如何告诉 __getitem__ 方法它返回的是什么类型。

我见过输入 self 的示例,但在这种情况下我需要输入 self.store。 mypy 可以将 self.store 的类型视为 dict(我假设它来自 Hasstore)但它不知道键或值类型。

这可能吗?

我是否需要更好地注释 Hasstore 协议的 store?我尝试过,例如 dict[str,T],但我无法使其工作,因为 T 如果像这样使用则不会被实例化。

我这样做的原因是使用 Mashumaro 将我的数据类序列化为 JSON,我无法弄清楚如何存储一个str 为键的普通字典而不在名为的数据类中创建单个属性store。所以有一些,它们都有一个名为 dictstore 所以我想我会使用 collections.abc.MutableMapping 来允许我通过下标访问 store,例如,twos["a"]。因此,我编写了mixin来做到这一点,但如果我不需要的话,丢失所有类型很遗憾。

感谢各位指点:)

解决方法

通用协议应该可以工作(文档在这里:https://mypy.readthedocs.io/en/stable/generics.html#generic-protocols):

T = TypeVar('T')


class HasStore(Protocol[T]):
    store: Dict[str,T]


class StoreGetMixin(HasStore[T]):

    def __getitem__(self,key: str) -> T:  # what to put in -> type?
        return self.store[key]


@dataclass
class ThingOne:
    size: int


@dataclass
class ThingTwo:
    name: str


@dataclass
class Ones(StoreGetMixin[ThingOne]):
    store: Dict[str,ThingOne] = field(default_factory=dict)


@dataclass
class Twos(StoreGetMixin[ThingTwo]):
    store: Dict[str,ThingTwo] = field(default_factory=dict)


ones = Ones()
ones.store = {"a": ThingOne(1),"b": ThingOne(2)}
one = ones["a"]  # <- this should be typed as a ThingOne
reveal_type(one)
twos = Twos()
twos.store = {"a": ThingTwo("one"),"b": ThingTwo("two")}
two = twos["a"]  # <- this should be typed as a ThingTwo
reveal_type(two)

输出为:

note: Revealed type is 'experiment.ThingOne*'
note: Revealed type is 'experiment.ThingTwo*'

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。