python - 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
as的类型dict
(我假设这来自HasStore
),但它不知道键或值类型。
这可能吗?
我需要更好地注释HasStore
协议store
吗?例如,我试过了,dict[str, T]
但我无法让它工作,因为T
如果这样使用它就不会被实例化。
我这样做的原因是使用 Mashumaro 将我的数据类序列化为 JSON,我无法弄清楚如何存储一个以 a 为键的普通字典,str
而无需在名为store
. 所以其中有一些,它们都有一个dict
被调用的store
,所以我想我会用它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*'
推荐阅读
- azure - 将多个 .NET Core 项目的测试覆盖率从 Azure DevOps 发布到 SonarQube 服务器
- flask - flask-sqlalchemy:数据库断开问题
- android - 服务将在哪个线程中运行?
- html - 当一行中的文本较少时无法对齐文本行
- javascript - 当鼠标进入窗口的顶部时做一些事情
- rust - 使用 trim_end_matches 作为闭包函数的类型不匹配:预期签名...找到“for<'r> ...”的签名
- php - PHP shell_exec 无法执行 Hadoop 命令
- objective-c - 如何通过 macOS 命令行工具使用 Apple 的 GameController 框架?
- java - 确定方法是否需要是静态的、私有的或非静态的
- python - 如何从链接获取文件大小而不用 python 下载?