2014-03-12 66 views
0

考慮下面的類:設置變異方法是否保留當前元素?

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) 
+2

什麼? ...集合是無序的...和不可變的...因此,我完全被你的問題困惑 –

+3

@JoranBeasley呃..集合是可變的,'frozenset's是不可變的。 – roippi

+0

ahh哎呀..對不起,即使發瘋,你對他們的可變性完全正確......但我堅持我早先所說的「什麼?」。 ...也是'&='是交集,所以我期望'set1&= set2'導致'set1 = {}',因爲沒有交集...... –

回答

1

documentation沒有提及二元運算是否莫名其妙地喜歡左或右參數,因此,我會說:該表達式的結果是實現定義的。在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中的集合的source code很明顯,當找到一個公共元素時,只有右操作數的元素被添加到結果中。在其他實現或版本中可能不是這種情況。


我只是在Python bug跟蹤系統開了一個issue看到這個信息是否可以被包含的文件中。

+0

+1我完全忽略了這一點 –

相關問題