考虑以下课程:
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)
答案 0 :(得分:1)
documentation没有提到二进制操作是否更喜欢左或右参数,因此我说该表达式的结果是实现定义的。在CPython上,第二个参数是交集的首选,而第一个参数是union首选,因为您可以轻松地测试:
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中的source code集中可以清楚地看到,当找到一个公共元素时,只有右操作数的元素被添加到结果中。在其他实现或版本中可能不是这种情况。
我刚刚在python bug跟踪器中打开issue,看看这些信息是否可以包含在文档中。