当将某些Python3 2/Qt4代码转换为Python3 3/Qt5时,我发现QStandardItem显然不能再用作dict,因为它没有实现__hash__,因此不再被认为是不可变的。
这两个片段显示了问题所在:
PyQt4:
>>> from PyQt4 import QtGui
>>> a = QtGui.QStandardItem()
>>> b = {}
>>> b[a] = "1"
>>> a.__hash__()
2100390PyQt5:
>>> 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__版本(我已经做过了)。但我遗漏了什么吗?
发布于 2017-12-11 20:25:15
在Qt中,有三个对可混性的要求:
==运算符。qHash函数。因此,如果PyQt想要保持与Qt的一致性,它应该只在上述条件适用时定义__hash__,并且它的实现应该简单地委托给Qt提供的任何qHash函数。
在PyQt4 4/5中使用Python2时的行为可能会被认为是错误的,因为它提供的结果与Qt不一致。这可以通过查看是可访问类型(以Qt术语表示)所发生的情况来看出:
使用Python 3:
>>> a = QtCore.QUrl('foo.bar')
>>> b = QtCore.QUrl('foo.bar')
>>> a == b
True
>>> hash(a) == hash(b)
True这正是我们想要的:比较相等的对象,也应该散列相等。但是现在看看在Python2中使用相同版本的PyQt时会发生什么:
>>> a = Qt.QUrl('foo.bar')
>>> b = Qt.QUrl('foo.bar')
>>> a == b
True
>>> hash(a) == hash(b)
FalsePython2中的__hash__实现似乎使用了类似于对象的标识,这显然与Qt的散列语义不一致。
QStandardItem类在Qt中是不可接受的,因此为了一致性起见,PyQt现在选择不为其提供__hash__方法。而且由于QStandardItem的实例实际上是可变的,所以PyQt相当合理地让用户来决定何时定义__hash__以及如何实现__hash__。为了与Python2兼容,这可能只返回id(self)。
https://stackoverflow.com/questions/47749631
复制相似问题