我有一个小的helper类:
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__
等方法。)
发布于 2017-12-01 00:25:09
在这种语言中,__req__
不是一个好主意,因为如果Left
类定义了__eq__
,而Right
类定义了__req__
,那么Python就必须一致地决定谁首先在Left() == Right()
中被调用。他们不可能都赢。
但是,Python数据模型确实允许您在这里做您想做的事情。您可以从两个方面控制这种比较,但您需要正确定义AnyOf
。如果希望从右侧控制AnyOf
np.ndarray
**.**的__eq__,则必须将其定义为的子类
如果我执行
AnyOf(2,3) == arr
,那么我的AnyOf
类的__eq__
方法永远不会被调用
不,你在这里有一个根本性的误解。除非右手边是左手边类型的子类,否则左手边总是在相等比较中得到第一次尝试。
arr == AnyOf(2,3)
在上面的例子中,你的自定义__eq__
被调用了,因为numpy数组调用了它!所以np.ndarray
赢了,它决定对每个元素检查一次。它实际上可以做任何其他事情,包括根本不调用你的AnyOf.__eq__
。
AnyOf(2,3) == arr
在上面的例子中,您的类进行了第一次比较,但由于使用in
(检查数组是否在元组中)的方式而失败。
发布于 2017-12-01 00:07:07
关于像__radd__
这样的__rxx__
方法的documentation声明:
仅当左操作数不支持相应的操作并且操作数属于不同类型时,才会调用这些函数。
虽然默认情况下类没有__add__
或__sub__
方法,但它们do __eq__
>>> class A(object):
... pass
>>> '__eq__' in dir(A)
True
这意味着__req__
永远不会被调用,除非您显式地从另一个类中删除__eq__
,或者使__eq__
返回NotImplemented
。
您可以使用np.in1d
解决您的特定问题
>>> np.in1d(arr, [2, 3])
array([False, True, True, False, False], dtype=bool)
发布于 2017-12-01 00:14:26
这是有关data model的文档
这些方法没有交换参数版本(当左边的参数不支持操作,而右边的参数支持时使用);相反,
__lt__()
和__gt__()
是彼此的反射,__le__()
和__ge__()
是对方的反射,__eq__()
和__ne__()
是它们自己的反射。如果两个操作数的类型不同,且右操作数的类型是左操作数类型的直接或间接子类,则右操作数的反射方法优先,否则左操作数的方法优先。不考虑虚拟子类化。
正如上面的注释所述,您想要的东西是有效的,__eq__
本质上与潜在的__req__
相同:如果左侧的对象返回NotImplemented
,则在==
的右侧调用它
In [1]: class A:
...: def __eq__(self, other):
...: return NotImplemented
...:
In [2]: class B:
...: def __eq__(self, other):
...: print("B comparing")
...: return True
...:
In [3]: B() == A()
B comparing
Out[3]: True
In [4]: A() == B()
B comparing
Out[4]: True
In [5]: A() == A()
Out[5]: False
当它出现时,它甚至可以与其他普通对象一起工作:
In [10]: 5 == B()
B comparing
Out[10]: True
然而,一些对象可能会在__eq__
上产生TypeError,而不是返回NotImplemented
或False
,这使得这对所有类型的对象都不可靠。
在您的例子中,是在您自己的__eq__
方法中不正确地使用了运算符in
和数组和元组。(感谢@wim在这里的另一个答案中发现了这一点)。
https://stackoverflow.com/questions/47577395
复制相似问题