首页 > 解决方案 > 在 Python 中,对象可以在创建后变为可散列吗?

问题描述

我想通过类 Wrapper 创建递归数据结构,并且我希望能够执行以下操作:

A = Wrapper()

A.assign_value((A, 5))

my_set = set()
my_set.add(A)

这要求 A 是可散列的,但其中一个要求是(根据文档):

它有一个在其生命周期内永远不会改变的哈希值

Wrapper 对象可以变得可散列,然后在集合和字典键中自由使用,只要assign_value只能使用一次,但我不确定这是否符合定义,因为值会在其生命周期内发生变化(即使值保证不再改变)。另外,我不确定我将如何实现一个__hash__有时指示“这个对象实际上不是可散列的”的函数,如果它甚至可能的话。在标准 Python 中,有效函数的存在似乎__hash__表明一个对象是可散列的,无论它在调用时返回什么。

我目前的想法是__hash__在实例而不是类中设置函数,如下所示:

class Wrapper():
    def __init__(self):
        self.assigned = False

    def _hash(self):
        return hash(Wrapper, self.val)

    def _eq(self, a):
        if isinstance(self, Wrapper) and a.assigned:
            return self.val == a.val
        return NotImplemented

    def assign_value(self, val):
        if self.assigned == True:
            raise NotImplementedError()
        self.assigned = True
        self.val = val
        self.__hash__ = self._hash
        self.__eq__ = self._eq

hash(A)在我给定的示例中,我意识到哈希函数将进入无限循环,不断尝试计算。__eq__也会面临这个问题,尽管在这种情况下,它可以像在 Python 中处理递归列表一样解决。设置一个用于 Wrapper 对象计算的默认哈希值(如hash(Wrapper))在理论上似乎确实解决了无限递归问题,使整个事情在技术上仍然可行。我也可以说def _hash(self): return 0,尽管 set 和 dicts 的性能成本。

这会按我的预期工作吗?这是最好的方法吗?最重要的是,我应该首先这样做吗?

标签: python

解决方案


推荐阅读