2009-11-10 105 views
0

我有以下代碼。類對象和比較特定屬性

class person(object): 

    def __init__(self, keys): 
     for item in keys: 
      setattr(self, item, None) 

    def __str__(self): 
     return str(self.__dict__) 

    def __eq__(self, other) :   
     return self.__dict__ == other.__dict__ 

現在我想利用這個代碼,並只做__eq__一組特定的attrs的(「鑰匙」)。所以我改成了這樣:

class person(object): 

    def __init__(self, keys): 
     self.valid_keys = keys 
     for item in keys: 
      setattr(self, item, None) 

    def __str__(self): 
     return dict([(i, getattr(self, i)) for i in self.valid_keys ]) 

    def __eq__(self, other) : 
     assert isinstance(other, person) 
     self_vals = [ getattr(self, i) for i in self.valid_keys ] 
     other_vals = [ getattr(other, i) for i in self.valid_keys ] 
     return self_vals == other_vals 

我已經閱讀了以下兩個真棒職位(herehere)和我的基本問題是:

這是正確的做法還是有更好的辦法在Python中做到這一點?

顯然TMTOWTDI - 但我想保持並遵循標準pythonic方法。謝謝!!

更新

有人問我,爲什麼我不能在我的課修復ATTRS。這是一個很好的問題,這就是爲什麼。這樣做的目的是取得幾個不相關的員工記錄並構建完整的員工照片。例如,我從ldap,lotus notes,unix passwd文件,bugzilla數據等獲取我的數據。每個人都有uniq attrs,因此我將它們推廣到一個人中。這使我能夠快速一致地將舊記錄與新記錄進行比較。 HTH。由於

**更新Pt.2 **

這裏是我結束了:

class personObj(object): 

    def __init__(self, keys): 
     self.__dict__ = dict.fromkeys(keys) 
     self.valid_keys = keys 

    def __str__(self): 
     return str([(i, getattr(self, i)) for i in self.valid_keys ]) 

    def __eq__(self, other): 
     return isinstance(other, personObj) and all(getattr(self, i) == getattr(other, i) for i in self.valid_keys) 

感謝兩個紳士審查!

+2

我不明白你的構造函數:你準備做一個人()並每次傳遞屬性列表?我會認爲這些屬性是人類的固定特徵。也許是它將如何被調用的一個例子? – 2009-11-10 15:43:36

+0

偉大的問題。我從一組固定的屬性開始,但我發現代表一個人的不同方式出現了。所以我想我只是通過一個attrs列表。我會擴展爲什麼我這樣做。好老鷹的眼睛。 – rh0dium 2009-11-10 16:46:24

+0

如我在答覆中提到的,如果'self'中有效的某些鍵從'other'中丟失,那麼您仍然會在'__eq__'中崩潰。 – 2009-11-11 00:19:19

回答

2

有小的改進(bug修復),我肯定會做。

特別是,如果屬性不存在,用兩個參數調用getattr會引發ArgumentError,因此如果您使用不同的鍵比較兩個實例,則可能會得到該異常。你可以用三個參數來調用它(當屬性不存在時,第三個返回爲默認值) - 在這種情況下,不要使用None作爲第三個參數,因爲它通常作爲值(使用一個sentinel值作爲第三個arg)。

__str__不允許返回字典:它必須返回一個字符串。

__eq__非可比對象之間不應該加 - 它應該返回False。

除此之外,您可以通過self.__dict__或者vars(self)更優雅地獲得對象的狀態(儘管如此,您不能使用後面的語法重新分配整個字典)。這種知識位可以讓你重做你的類完全,在更高級別的抽象的方式 - 更緊湊,更迅速:

class person(object): 

    def __init__(self, keys): 
     self.__dict__ = dict.fromkeys(keys) 

    def __str__(self): 
     return str(vars(self)) 

    def __eq__(self, other): 
     return isinstance(other, person) and vars(self) == vars(other) 
+0

亞歷克斯, 我總是喜歡研究你的帖子。毫無疑問,您的知識和分享意願是一流的。謝謝 – rh0dium 2009-11-10 17:05:32

+0

在審查你的代碼之後 - 你沒有完全做我以後的事 - 所以我已經更新了我的學習。 – rh0dium 2009-11-10 21:06:14

+0

正如我在你編輯的Q中所評論的,如果我在上面的回答中提到過,如果'self'中有效的某些鍵從'other'丟失,你仍然會在'__eq__'中崩潰。另外,你的'__eq__'不一定是可交換的(也許a == b是真的[[或false]],但是b == a崩潰了......可怕的!)。所以我還不清楚你想要做什麼。也許可以進一步編輯答案,以提供一些應該相等與不同的人物實例的玩具示例? – 2009-11-11 00:21:10

1

您可以簡化從對比:

self_vals = [ getattr(self, i) for i in self.valid_keys ] 
other_vals = [ getattr(other, i) for i in self.valid_keys ] 
return self_vals == other_vals 

到:

return all(getattr(self, i) == getattr(other, i) for i in self.valid_keys) 
+0

真棒 - 我用這個! – rh0dium 2009-11-10 20:51:52