Python: 你能让这个 __eq__ 更易懂吗?
我还有一个问题想问你。
我有一个Python类,里面有一个叫做'metainfo'的列表。这个列表里包含了我这个类可能会有的变量名。我写了一个__eq__
方法,如果self
和other
这两个对象在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 个回答
在编程中,有时候我们会遇到一些问题,可能是因为代码写得不够清晰,或者是我们对某些概念理解得不够透彻。比如,有人可能会在使用某个功能时,发现它的表现和自己预期的不一样。这种情况很常见,尤其是对于刚开始学习编程的小伙伴们来说。
在这种情况下,最重要的是要耐心分析问题,看看是不是哪里出了错。可以尝试把代码分成小块,逐步调试,找出问题所在。同时,也可以参考一些在线资源,比如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
我建议你加一个文档字符串,来解释一下这个代码是用来比较什么的,就像你在问题中提到的那样。
使用 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, ...)
等等。其实,不要这么做 :)