gpt4 book ai didi

Python - __eq__ 方法未被调用

转载 作者:太空狗 更新时间:2023-10-30 02:05:29 27 4
gpt4 key购买 nike

我有一组对象,并且有兴趣从该组中获取特定对象。经过一番研究,我决定使用此处提供的解决方案:http://code.activestate.com/recipes/499299/

问题是它似乎不起作用。

我定义了两个类:

class Foo(object):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def __key(self):
return (self.a, self.b, self.c)
def __eq__(self, other):
return self.__key() == other.__key()
def __hash__(self):
return hash(self.__key())

class Bar(Foo):
def __init__(self, a, b, c, d, e):
self.a = a
self.b = b
self.c = c
self.d = d
self.e = e

注意:这两个类的相等性只能定义在属性a、b、c上。

http://code.activestate.com/recipes/499299/ 中的包装器 _CaptureEq还定义了自己的 __eq__ 方法。问题是这个方法永远不会被调用(我认为)。考虑一下,

bar_1 = Bar(1,2,3,4,5)
bar_2 = Bar(1,2,3,10,11)
summary = set((bar_1,))
assert(bar_1 == bar_2)
bar_equiv = get_equivalent(summary, bar_2)

bar_equiv.d 应该等于 4,同样 bar_equiv.e 应该等于 5,但它们不是。正如我提到的,当执行语句 bar_2 in summary 时,看起来 __CaptureEq __eq__ 方法没有被调用。

__CaptureEq __eq__ 方法没有被调用有什么原因吗?希望这不是一个太晦涩的问题。

最佳答案

Brandon 的回答提供了信息,但不正确。实际上有两个问题,一个是依赖于 _CaptureEq 的配方被编写为旧式类(因此,如果您在 Python 3 上使用基于散列的容器尝试它,它将无法正常工作),以及一个具有您自己的 Foo.__eq__ 明确声明两个对象不相等的定义,而它应该说“我不知道,请问另一个对象我们是否相等”。

配方问题很容易解决:只需在比较包装类上定义 __hash__:

class _CaptureEq:
'Object wrapper that remembers "other" for successful equality tests.'
def __init__(self, obj):
self.obj = obj
self.match = obj
# If running on Python 3, this will be a new-style class, and
# new-style classes must delegate hash explicitly in order to populate
# the underlying special method slot correctly.
# On Python 2, it will be an old-style class, so the explicit delegation
# isn't needed (__getattr__ will cover it), but it also won't do any harm.
def __hash__(self):
return hash(self.obj)
def __eq__(self, other):
result = (self.obj == other)
if result:
self.match = other
return result
def __getattr__(self, name): # support anything else needed by __contains__
return getattr(self.obj, name)

您自己的 __eq__ 定义的问题也很容易解决:在适当的时候返回 NotImplemented,这样您就不会声称为与未知对象的比较提供了明确的答案:

class Foo(object):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def __key(self):
return (self.a, self.b, self.c)
def __eq__(self, other):
if not isinstance(other, Foo):
# Don't recognise "other", so let *it* decide if we're equal
return NotImplemented
return self.__key() == other.__key()
def __hash__(self):
return hash(self.__key())

通过这两个修复,您会发现 Raymond 的 get_equivalent 方法完全可以正常工作:

>>> from capture_eq import *
>>> bar_1 = Bar(1,2,3,4,5)
>>> bar_2 = Bar(1,2,3,10,11)
>>> summary = set((bar_1,))
>>> assert(bar_1 == bar_2)
>>> bar_equiv = get_equivalent(summary, bar_2)
>>> bar_equiv.d
4
>>> bar_equiv.e
5

更新:澄清了只有在正确处理 Python 3 情况下才需要显式 __hash__ 覆盖。

关于Python - __eq__ 方法未被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11182624/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com