考虑以下类:
class MyObj:
def __init__(self, key, value):
self.key = key
self.value = value
def __key(self):
return self.key
def __hash__(self):
return hash(self.__key())
def __eq__(self, other):
return type(self) is type(other) and self.__key() == other.__key()
set1 = {MyObj(1,'a'), MyObj(3,'a'), ...}
set2 = {MyObj(1,'b'), MyObj(2,'b'), ...}
是否保证set1 &= set2
之后,set1
是{MyObj(1,'a'), ...}
而不是MyObj(1,'b'), ...
?
是否同样适用于其他突变方法,如union_update
, difference_update
?
更新:如果需要保留左边的元素,可以使用下面的命令:
set1 -= (set1-set2)
文档没有提到二进制操作是更喜欢左参数还是右参数,因此我说过该表达式的结果是实现定义的。在CPython上,第二个参数优先用于交集,而第一个参数优先用于联合,因为你可以很容易地测试:
In [1]: class MyObj:
...: def __init__(self, key, value):
...: self.key = key
...: self.value = value
...: def __key(self):
...: return self.key
...: def __hash__(self):
...: return hash(self.__key())
...: def __eq__(self, other):
...: return type(self) is type(other) and self.__key() == other.__key()
In [2]: a = {MyObj(1, 'a')}
In [3]: b = {MyObj(1, 'b')}
In [4]: a & b
Out[4]: set([<__main__.MyObj at 0x7f4b5c17c650>])
In [5]: (a & b).pop().value
Out[5]: 'b'
In [6]: (b & a).pop().value
Out[6]: 'a'
(这个例子也表明另一个答案是错误的,因为是的交集)
从CPython中集合的源代码可以清楚地看出,当找到一个公共元素时,只将右操作数的元素添加到结果中。在其他实现或版本中可能不是这种情况。
我刚刚在python bug tracker中打开了一个问题,看看这些信息是否可以包含在文档中。