当前在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/

    10-09 17:11