设置变化的方法保留当前元素



考虑以下类:

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中打开了一个问题,看看这些信息是否可以包含在文档中。

相关内容

最新更新