Python: 你能让这个 __eq__ 更易懂吗?

4 投票
9 回答
3216 浏览
提问于 2025-04-15 16:25

我还有一个问题想问你。

我有一个Python类,里面有一个叫做'metainfo'的列表。这个列表里包含了我这个类可能会有的变量名。我写了一个__eq__方法,如果selfother这两个对象在metainfo里有相同的变量,并且这些变量的值也相同,就会返回True。

这是我的实现代码:

 def __eq__(self, other):
    for attr in self.metainfo:
      try:
        ours = getattr(self, attr) 
        try:
          theirs = getattr(other, attr)
          if ours != theirs:
            return False
        except AttributeError:
          return False
      except AttributeError:
        try:
          theirs = getattr(other, attr)
          return False
        except AttributeError:
          pass
    return True

有没有人能给我一些建议,让这段代码看起来更简洁一些?请尽管提意见。

9 个回答

5

在编程中,有时候我们会遇到一些问题,可能是因为代码写得不够清晰,或者是我们对某些概念理解得不够透彻。比如,有人可能会在使用某个功能时,发现它的表现和自己预期的不一样。这种情况很常见,尤其是对于刚开始学习编程的小伙伴们来说。

在这种情况下,最重要的是要耐心分析问题,看看是不是哪里出了错。可以尝试把代码分成小块,逐步调试,找出问题所在。同时,也可以参考一些在线资源,比如StackOverflow,那里有很多经验丰富的程序员分享他们的解决方案和经验。

记住,编程是一个不断学习和实践的过程,遇到问题时不要气馁,慢慢来,总会找到解决办法的。

def __eq__(self, other):
    """Returns True if both instances have the same variables from metainfo
    and they have the same values."""
    for attr in self.metainfo:
        if attr in self.__dict__:
            if attr not in other.__dict__:
                return False
            if getattr(self, attr) != getattr(other, attr):
                return False
            continue
        else:
            if attr in other.__dict__:
                return False
    return True
9

我建议你加一个文档字符串,来解释一下这个代码是用来比较什么的,就像你在问题中提到的那样。

9

使用 getattr 的第三个参数可以设置不同的默认值:

def __eq__(self, other):
    return all(getattr(self, a, Ellipsis) == getattr(other, a, Ellipsis)
               for a in self.metainfo)

作为默认值,可以设置一个永远不会是实际值的东西,比如 Ellipsis。这样,只有当两个对象在某个属性上有相同的值,或者两个对象都没有这个属性时,值才会匹配。

编辑:正如 Nadia 指出的那样,NotImplemented 可能是一个更合适的常量(除非你在存储复杂比较的结果...)。

编辑 2:确实,正如 Lac 指出的那样,直接使用 hasattr 会得到一个更易读的解决方案:

def __eq__(self, other):
    return all(hasattr(self, a) == hasattr(other, a) and
               getattr(self, a) == getattr(other, a) for a in self.metainfo)

  : 为了增加一些神秘感,你可以用 ... 代替 Ellipsis,这样就变成 getattr(self, a, ...) 等等。其实,不要这么做 :)

撰写回答