我发现在将一些 Python2/Qt4 代码转换为 Python3/Qt5 时,显然 QStandardItem 不能再用作字典键,因为它没有__hash__
已实施,因此不再被认为是不可变的。
这两个片段显示了这个问题:
PyQt4:
>>> from PyQt4 import QtGui
>>> a = QtGui.QStandardItem()
>>> b = {}
>>> b[a] = "1"
>>> a.__hash__()
2100390
PyQt5:
>>> from PyQt5 import QtGui
>>> a = QtGui.QStandardItem()
>>> b = {}
>>> b[a] = "1"
TypeError: unhashable type: 'QStandardItem'
>>> a.__hash__()
TypeError: 'NoneType' object is not callable
为什么要进行更改?我不应该使用 QStandardItem 作为字典键吗?
明显的解决方法是子类化 QStandardItem 并重新实现一个简单的版本__hash__
(我已经做到了)。但我有什么遗漏的吗?
在Qt中,有三个可散列性要求:
- 该类型必须是可分配的数据类型
- 该类型必须定义一个
==
操作员
- a
qHash
必须为类型定义函数
因此如果PyQt想要与Qt保持一致,它应该只定义__hash__
当上述条件适用时,其实现应该简单地委托给任何人qHash
Qt 提供的函数。
将 Python 2 与 PyQt4/5 一起使用时的行为可能应该被视为错误功能,因为它给出的结果是not与Qt一致。通过查看以下类型会发生什么就可以看出这一点is可哈希(Qt 术语):
使用Python 3:
>>> a = QtCore.QUrl('foo.bar')
>>> b = QtCore.QUrl('foo.bar')
>>> a == b
True
>>> hash(a) == hash(b)
True
这正是我们想要的:对象compare平等,也应该hash平等的。但现在看看当使用相同版本的 PyQt 和 Python 2 时会发生什么:
>>> a = Qt.QUrl('foo.bar')
>>> b = Qt.QUrl('foo.bar')
>>> a == b
True
>>> hash(a) == hash(b)
False
似乎有类似物体的东西identity被使用的是__hash__
Python 2 中的实现,显然与 Qt 的哈希语义不一致。
The QStandardItem
班级有never在 Qt 中是可哈希的,因此为了一致性,PyQt 现在选择不提供__hash__
的方法。并且自从实例QStandardItem
事实上,它们是可变的,PyQt 相当合理地将其留给用户来决定何时定义__hash__
,以及如何实施。为了与 Python 2 兼容,这可能会返回id(self)
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)