我有一个小助手类:
class AnyOf(object):
def __init__(self, *args):
self.elements = args
def __eq__(self, other):
return other in self.elements
这让我可以像这样施展甜蜜魔法:
>>> arr = np.array([1,2,3,4,5])
>>> arr == AnyOf(2,3)
np.array([False, True, True, False, False])
无需使用列表理解(如 np.array(x in (2,3) for x in arr
)。
(我维护了一个 UI,允许(受信任的)用户输入任意代码,并且 a == AnyOf(1,2,3)
比列表理解更容易接受-精通技术的用户。)
但是!
这只有一种方法!例如,如果我要执行 AnyOf(2,3) == arr
那么我的 AnyOf
类的 __eq__
方法永远不会被调用:相反, NumPy 数组的 __eq__
方法被调用,它在内部(我假设)调用其所有元素的 __eq__
方法。
这让我想知道:为什么 Python 不允许右侧等价于 __eq__
? (大致等同于 __radd__
、__rmul__
等方法。)
最佳答案
在语言中,__req__
可能被认为比有用 更令人困惑。考虑如果类 Left
定义了 __eq__
而类 Right
定义了 __req__
,那么 Python 有义务做一个 在 Left() == Right()
中谁先被调用的决定是一致的(我们可能希望结果是等价的,无论哪种方式)。他们不可能都赢。
但是,Python 数据模型确实允许您在这里做您想做的事情。您可以从任何一方控制此比较,但您需要以特定方式定义 AnyOf
。 如果您希望AnyOf
从右侧控制eq,您可以将其定义为np.ndarray
的子类.
if I were to do
AnyOf(2,3) == arr
then myAnyOf
class's__eq__
method never gets called
实际上,不,这里存在明显的根本误解。左侧总是首先尝试进行相等比较,除非右侧是左侧类型的子类。
arr == AnyOf(2,3)
在上面显示的比较中,您的自定义 __eq__
正在 被调用,因为 numpy 数组调用它!所以 np.ndarray
获胜,它决定对每个元素检查一次。它实际上可以做任何其他事情,包括根本不调用您的 AnyOf.__eq__
。
AnyOf(2,3) == arr
在上面显示的比较中,您的类确实在比较中进行了第一次尝试,但由于使用了 in
的方式而失败了 - return other in self.elements
正在检查数组是否在元组中。
关于python - 为什么 Python 没有 "__req__"(反射(reflect)相等)方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47577395/