set mutating方法是否保留当前元素?

时间:2014-03-12 20:50:00

标签: python set

考虑以下课程:

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_updatedifference_update等其他变异方法吗?

更新: 如果您需要保留左侧元素,请使用以下内容:

set1 -= (set1-set2)

1 个答案:

答案 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,看看这些信息是否可以包含在文档中。