2009-11-10 85 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