【问题标题】:Class Objects and comparing specific attributes类对象和比较特定属性
【发布时间】:2010-12-15 02:21:26
【问题描述】:

我有以下代码。

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__

现在我想使用此代码,并且只对一组特定的 attrs(“键”)执行 __eq__。所以我把它改成这样:

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 - 但我想保留并遵循标准的 Python 方法。谢谢!!

更新

有人问我为什么不修复课堂上的属性。这是一个很好的问题,这就是为什么。这样做的目的是获取多个不连贯的员工记录并构建员工的完整图片。例如,我从 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)

感谢两位先生的审阅!

【问题讨论】:

  • 我不明白你的构造函数:你要创建一个 person() 并每次都传入属性列表?我原以为属性将是人员类的固定特征。也许是一个如何调用它的例子?
  • 好问题。我从一组固定的属性开始,但我发现代表一个人的不同方式出现了。所以我想我只是传递一个attrs列表。我将扩展我这样做的原因。好鹰眼。
  • 如果other 中缺少某些在self 中有效的键,您仍然会在__eq__ 中崩溃,正如我在回答中提到的那样。

标签: coding-style python


【解决方案1】:

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

特别是,getattr 使用两个参数调用会在属性不存在时引发 ArgumentError,因此如果您比较具有不同键的两个实例,您可能会遇到该异常。你可以用三个参数来调用它(当属性不存在时,第三个作为默认值返回)——在这种情况下不要使用 None 作为第三个参数,因为它是你通常拥有的值(使用标记值作为第三个参数)。

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

__eq__ 在不可比较的对象之间不应该引发——它应该返回 False。

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

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)

【讨论】:

  • Alex,我一直很喜欢研究你的帖子。毫无疑问,您的知识和分享它的意愿是一流的。谢谢
  • 在审查了你的代码之后——你并没有完全按照我的要求去做——所以我更新了我的学习。
  • 正如我还评论了您编辑的 Q,如果 self 中的某些有效键在 other 中丢失,您仍然会在 __eq__ 中崩溃,正如我在回答中提到的那样更多。此外,您的 __eq__ 不一定是可交换的(也许 a==b 为真 [[或假]] 但 b==a 崩溃......可怕!_)。所以我仍然不清楚你想要做什么。也许进一步编辑答案以给出几个应该相同与不同的人实例的玩具示例?
【解决方案2】:

您可以通过以下方式简化比较:

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)

【讨论】:

    猜你喜欢
    • 2016-07-16
    • 2012-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多