Mar*_*ark 0 python hash dictionary
我遇到的问题分布在许多源文件中,我以简单的线性格式重现问题的尝试失败了。尽管如此,我遇到的问题只是简单地描述了。
我有一个类Path为我实现__hash__和__eq__
我有一个类型Path为 a的项目,dict证明如下
path in list(thedict)
>> True
Run Code Online (Sandbox Code Playgroud)
我确认path == other,并hash(path) == hash(other)和id(path) == id(other)那里other取直出的项目list(thedict.keys())。然而,我得到以下
path in thedict:
>> False
Run Code Online (Sandbox Code Playgroud)
并尝试以下结果 KeyError
thedict[path]
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,在什么情况下这可能?我原以为如果path是 inlist(thedict)那么它必须在thedict.keys(),因此我们必须能够写thedict[path]. 这个假设有什么问题?
如果有帮助,下面列出了有问题的类。正是在SpecificationPath上述问题被观察到的水平
class Path:
pass
@dataclass
class ConfigurationPath(Path):
configurationName: str = None
def __repr__(self) -> str:
return self.configurationName
def __hash__(self):
return hash(self.configurationName)
def __eq__(self, other):
if not isinstance(other, ConfigurationPath):
return False
return self.configurationName == other.configurationName
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@dataclass
class SpecificationPath(Path):
configurationPath: ConfigurationPath
specificationName: str = None
def __repr__(self) -> str:
return f"{self.configurationPath}.{self.specificationName or ''}"
def __hash__(self):
return hash((self.configurationPath, self.specificationName))
def __eq__(self, other):
if not isinstance(other, SpecificationPath):
return False
if self.configurationPath != other.configurationPath:
return False
if self.specificationName != other.specificationName:
return False
return True
Run Code Online (Sandbox Code Playgroud)
为了回应下面的评论,这里是 (Spyder) 调试终端中的输出,其中pf是一个包含paths使用路径作为键的字典的对象,并且有问题的对象 ( self) 具有路径。
In : others = list(pf.paths.keys())
In : other = others[1]
In : self.path is other
Out[1]: True
In : self.path in pf.paths
Out[1]: False
Run Code Online (Sandbox Code Playgroud)
根据您的评论:
该路径确实希望是可变的,因为我设置
specificationName到None的地方(让他们匿名稍后填写)。此外,在这样的情况:在specificationName为None出现这种情况,但是在我的简单测试脚本我可以逃脱没有一个错误此设置为无。可散列实例的可变性是否会导致这样的错误?
那是你的问题。您dict在创建后立即将这些对象放入 a 中,而specificationNameis None,因此它dict使用基于的哈希码存储在中None(该哈希码缓存在dict自身中,并且使用该哈希码是将来查找对象的唯一方法)。如果随后将其更改为任何东西产生不同的散列值(读取几乎所有其他),对象存储在对应于旧的散列码一斗,但用它来查找计算新的散列码并不能找到桶。
如果specificationName必须是可变的,那么它就不能成为散列的一部分,就这么简单。这可能会增加碰撞,但无济于事;如果不触发这个确切的问题,可变字段就不能成为散列的一部分。
| 归档时间: |
|
| 查看次数: |
67 次 |
| 最近记录: |