python - 在 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 的性能成本。
这会按我的预期工作吗?这是最好的方法吗?最重要的是,我应该首先这样做吗?
解决方案
推荐阅读
- c# - Xamarin Forms - ViewCell 中 BindingContext 中的多个项目
- java - 给定两个表示路径的数组的 Java 小练习
- javascript - 确保清理代码在异步 QUnit 上下文中运行
- javascript - 检查时的空白是什么?
- xcode - 使用 CocoaPods 时的 Xcode 12 部署目标警告
- javascript - 检查多个字符中的 1 个是否在字符串中,如果至少有一个则返回 true
- python - Python 被多个条件吐出
- node.js - 即使一些被拒绝或仍在进行中,如何等待一个承诺完成?
- flutter - 为两列信息适当调整框的大小,但两列的最小大小
- android - 我可以为参数值提供两个选项吗?