簡體   English   中英

QStandardItem 缺少 __hash__ 方法

[英]QStandardItem missing __hash__ method

我發現在將一些 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 中,對 hashability有三個要求

  1. 類型必須是可分配的數據類型
  2. 類型必須定義一個==運算符
  3. 必須為該類型定義一個qHash函數

所以如果 PyQt 想要保持與 Qt 的一致性,它應該只在滿足上述條件時定義__hash__ ,並且它的實現應該簡單地委托給 Qt 提供的任何qHash函數。

使用Python 2 PyQt4的時的行為/ 5也許應該被認為是不好的特性,因為它使結果使用Qt一致。 這可以通過查看散列類型(用 Qt 術語)發生的情況來看出:

使用 Python 3:

>>> a = QtCore.QUrl('foo.bar')
>>> b = QtCore.QUrl('foo.bar')
>>> a == b
True
>>> hash(a) == hash(b)
True

這正是我們想要的:比較相等的對象,也應該哈希相等。 但是現在看看在 Python 2 中使用相同版本的 PyQt 時會發生什么:

>>> a = Qt.QUrl('foo.bar')
>>> b = Qt.QUrl('foo.bar')
>>> a == b
True
>>> hash(a) == hash(b)
False

似乎 Python 2 中的__hash__實現使用了類似於對象標識的東西,這顯然永遠不會與 Qt 的散列語義一致。

QStandardItem類在 Qt 中從未可散列,因此為了一致性,PyQt 現在選擇不為其提供__hash__方法。 由於QStandardItem實例實際上是可變的,PyQt 相當合理地讓用戶決定何時定義__hash__以及如何實現它。 為了與 Python 2 兼容,這可能只返回id(self)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM