【问题标题】:why are custom objects hashable (and usable in dict) in python?为什么自定义对象在 python 中是可散列的(并且可以在 dict 中使用)?
【发布时间】:2018-04-26 00:05:19
【问题描述】:

新手问题:为了将对象用作dict 中的键,它需要是可散列的。很明显,不可变类型可以用作键,而可变类型不能。但是,如果我定义一个可变的类,显然它仍然可以用作键。在下面的代码中my_obj 是对包含RandomObject 类型对象的内存槽的引用。该内存插槽包含对 25 的引用 (x),但此引用可以更改为指向其他任何内容。这让我很困惑,为什么它会起作用?此外,my_obj 可以引用RandomObject 的全新实例。如果散列发生在实际对象(而不是引用的内存地址)上,这将如何工作?

class RandomObject:
    def __init__(self, x):
        self._x = x

d = {"hi": 1, "bye": 2}
my_obj = RandomObject(25)
d[my_obj] = 3
print(d)
#{'hi': 1, 'bye': 2, <__main__.RandomObject object at 0x0000000005B75D30>: 3}

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    您的类继承了object.__eq__object.__hash__,它们通过身份工作。散列并不直接关心可变性。它只关心影响== 比较的可变性。当== 是身份时,不会有任何突变影响== 的比较。

    【讨论】:

    • 我明白了,一定是list 之类的东西定义了自己的__eq__,它通过值而不是列表本身的实际身份来比较列表中的内容?即为什么可变类型不是可散列的
    • @Alex: list.__eq__ 不能通过身份工作。 list 相等比较受突变影响,因此列表禁止散列。
    • 有道理。那么,所有可变类型都定义自己的__eq__ 并因此破坏散列,这通常是真的吗?刚刚测试过,如果我在课堂上重载__eq__,它也不会散列
    • 下一个级别是没有什么能阻止您在可变类上定义自定义__hash__。毕竟这是 Python。
    猜你喜欢
    • 2010-12-29
    • 2015-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多