当前在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(在评论中)建议
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
doesn't offer an Intersection
type yet以来,您无法正确键入self
arg(并且Union
不能替代!)。您可以做的是为mixin引入基类,仅用于类型检查。这是在Django项目中使用mixins时经常使用的技巧。例:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .plugin import HW_PluginBase
_Base = HW_PluginBase
else:
_Base = object
class QtPluginBase(_Base):
def load_wallet(self, wallet: 'Abstract_Wallet', window: ElectrumWindow):
...
现在,您可以删除
self
的显式类型,因为mypy
可以推断所有必需的基类本身。关于python - 如何让Mypy与彼此依赖的多个mixins一起工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59311963/