【发布时间】:2022-10-12 21:24:13
【问题描述】:
首先,我正在使用类似于PEP-0478 的插件系统工作的项目使用PriortyQueue 来确保插件以正确的顺序运行。我将省略它的工作原理:
- 在 PEP-487 中有详细记录
- 理解此问题并不直接需要。
首先,我有以下基本课程:
# abstract.py import abc from dataclasses import data, field @dataclass(order=True) class PluginBase(abc.ABC): value: int def __eq__(self, __o: object) -> bool: print("PluginBase __eq__ called") return self.value == __o.value # plugin_a.py from abstract import PluginBase class PluginA(PluginBase): pass # plugin_b.py from abstract import PluginBase class PluginB(PluginBase): pass首先,在插件被发现并加载后,它们被包裹在
dataclass中,这是为了确保每个插件的代码量最少。问题:
__eq__()永远不会传递给子类。我如何设置课程甚至使用
funtools.total_ordering都没有关系。我注意到的一件事是,如果你这样做
assert PluginA(1) == PluginB(1)总是返回 false 并且assert PluginA(1) < PluginB(2)总是返回TypeError: '<' not supported between instances与当前类。这一直是故意的?
要解决第一个问题,
==不起作用,您需要添加:def __eq__(self, __o: object) -> bool: print("Plugin __eq__ called") return super().__eq__(__o)向一个或两个子类添加更多我不想要的插件系统的样板代码。
要修复 '<' 问题,您需要将
PluginBase更改为:@functools.total_ordering @dataclass class PluginBase(abc.ABC): value: int def __eq__(self, __o: object) -> bool: print("PluginBase __eq__ called") return self.value == __o.value def __lt__(self, __o: object) -> bool: print("PluginBase __lt__ called") return self.value < __o.value这允许您执行
PluginA(1) < PluginB(2),这将是true。但是,==在这里仍然不起作用。我认为这是由于类实例的差异,Python 强制
__eq__()先检查实例类型。反正有没有让这个工作?一种解决方案是将每个插件包装到一个可比较的对象中并将其用于队列。
【问题讨论】:
-
它对我有用,还有三行来定义对象并进行比较。也许你可以发布一个复制品。 (这里指的是==)
-
1)您的抽象基类没有抽象方法。 2)您的数据类覆盖了您的显式
__eq__方法,因为您没有将eq=False传递给装饰器。 3) 您的__eq__方法错误地假定object类型的值将具有value属性。如果没有,您可能应该返回NotImplemented。 -
您的问题非常令人困惑,因为您在描述问题的代码中包含了 __eq__ 覆盖,因此该代码实际上可以工作,因此很难理解您希望它工作没有它,仅使用数据类自动生成的比较器,这是我在下面理解和回答的