Jan*_*sen 7 python multiple-inheritance generic-programming python-3.x mypy
目前,在 Electrum 中,我们使用Unionon 类型self来访问来自多个混合父类的方法。例如,QtPluginBase依靠混合到 的子类中来HW_PluginBase工作。例如,有效的用途是class TrezorPlugin(QtPluginBase, HW_PluginBase).
有 Qt gui、Kivy gui,还有 CLI。尽管 Kivy 尚未实现硬件钱包,但未来可能会实现。您已经可以在 CLI 上使用它们。
然而,也有多家硬件钱包制造商,都有自己的插件。
考虑 Trezor + Qt:
对于 Qt,我们有这样的类层次结构:
electrum.plugins.hw_wallet.qt.QtPluginBase被使用过electrum.plugins.trezor.qt.QtPlugin(QtPluginBase)对于 Trezor,我们有:
electrum.plugin.BasePlugin被使用过electrum.plugins.hw_wallet.plugin.HW_PluginBase(BasePlugin)被使用过electrum.plugins.trezor.trezor.TrezorPlugin(HW_PluginBase)创建实际的 Qt Trezor 插件:
electrum.plugins.trezor.qt.Plugin(TrezorPlugin, QtPlugin)关键是基本的 gui 中立插件将首先获得制造商特定的方法;然后它将获得 GUI 特定的方法。
Aaron(在评论中)建议QtPluginBase可以 subclass HW_PluginBase,但这意味着制造商特定的内容将出现在后面,这意味着生成的类不能被 CLI 或 Kivy 使用。
请注意,两者
electrum.plugins.trezor.trezor.TrezorPlugin(HW_PluginBase)
和
electrum.plugins.hw_wallet.qt.QtPluginBase
依靠HW_PluginBase。他们不能都将其子类化。
因此,如果我们避免混合,那么唯一的选择就是要么有QtPluginBase子类TrezorPlugin(但有很多制造商),要么TrezorPlugin可以子类化QtPluginBase,但同样,生成的类不能被 CLI 或 Kivy 使用。
我意识到这Union是一个“或”,所以这个提示确实没有意义。但没有Intersection类型。通过 Union,大多数 PyCharm 功能都可以工作。
一件好事是,如果QtPluginBase可以有一个类型提示,表明它是子类化的HW_PluginBase,但在运行时实际上没有子类化。
如何使用 Mypy 键入此内容,而不必Union在每个方法上使用这种 hacky 类型提示(因为每个方法都有self)?
通过PEP-544 (Python 3.8+)中添加的协议,您可以自己定义交集接口!这还可以让您隐藏ClassA您不想ClassB使用的实现细节。
from typing import Protocol
class InterfaceAB(Protocol):
def method_a(self) -> None: ...
def method_b(self) -> None: ...
class ClassA:
def method_a(self) -> None:
print("a")
class ClassB:
def method_b(self: InterfaceAB) -> None:
print("b")
self.method_a()
# if I remove ClassA here, I get a type checking error!
class AB(ClassA, ClassB): pass
ab = AB()
ab.method_b()
# % mypy --version
# mypy 0.761
# % mypy mypy-protocol-demo.py
# Success: no issues found in 1 source file
Run Code Online (Sandbox Code Playgroud)
此文件的初始版本归功于 SomberNight/ghost43。
| 归档时间: |
|
| 查看次数: |
2093 次 |
| 最近记录: |