关于编码样式:类对象和比较特定属性

Class Objects and comparing specific attributes

我有以下代码。

1
2
3
4
5
6
7
8
9
10
11
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__

现在我想使用这段代码,并且只在一组特定的attr("keys")上执行__eq__。所以我把它改成这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

我读过以下两篇精彩的文章(这里和这里),我的基本问题是:

这是正确的方法还是有更好的方法在Python中实现这一点?

很明显,我想保持和遵循标准的Python疗法。谢谢!!

更新

有人问我,为什么我不把课上的注意力集中起来。这是一个很好的问题,原因如下。这样做的目的是为了获取几个不连贯的员工记录,并建立一个完整的员工照片。例如,我从LDAP、Lotus Notes、Unix passwd文件、Bugzilla数据等获取数据。这些文件中的每一个都有uniq属性,因此我将它们归纳为一个人。这给了我一个快速一致的方法来比较旧记录和新记录。Hth.谢谢

**更新第2部分**

以下是我最后得出的结论:

1
2
3
4
5
6
7
8
9
10
11
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)

感谢两位男士的检阅!


我肯定会做一些小的改进(错误修复)。

尤其是,如果属性不存在,使用两个参数调用getattr会引发一个argumentError,因此,如果比较两个具有不同键的实例,则可能会得到该异常。您可以用三个参数来调用它(当属性不存在时,返回第三个参数作为默认值)--在这种情况下,不要使用None作为第三个参数,因为它是您通常使用的值(使用sentinel值作为第三个参数)。

__str__不允许返回dict:它必须返回一个字符串。

不可比对象之间的__eq__不应上升——应返回假。

除了bug之外,您可以使用self.__dict__非常紧凑地获取对象的状态,或者使用vars(self)更加优雅地获取对象的状态(不过,不能使用后一种语法重新分配整个dict)。这一点知识可以让您以更高层次的抽象方式完全重做您的课程——更紧凑、更迅速:

1
2
3
4
5
6
7
8
9
10
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)


您可以从以下方面简化比较:

1
2
3
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

到:

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