【发布时间】:2020-04-06 06:43:39
【问题描述】:
目前在 Electrum 中,我们使用 Union type on 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-neutral插件将首先获得制造商特定的方法;那么它将获得特定于 gui 的方法。
Aaron(在 cmets 中)建议 QtPluginBase 可以继承 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 输入,而不必在每个方法上使用这个 hacky Union 类型提示(因为每个方法都有 self)?
【问题讨论】:
-
我会尝试深入挖掘,但我的第一个方法是创建自定义类型别名以及基类:mypy.readthedocs.io/en/latest/kinds_of_types.html#type-aliases
-
@JanusTroelsen 我试图用你的“Union type on self”创建一个 MCVE,但我得到了
error: Item "QtPluginBase" of "Union[QtPluginBase, HW_PluginBase]" has no attribute "keystore_class"。 -
@aaron 这是来自 Mypy 的错误吗?我看到
keystore_classdefined in HW_PluginBase,不知道为什么Mypy不识别? -
@JanusTroelsen 这似乎是正确的。
Union表示or。QtPluginBase没有keystore_class。如果它的方法直接依赖于它,为什么它不继承HW_PluginBase?
标签: python python-3.x multiple-inheritance generic-programming mypy