Dictionary mit Keys vom Typ QDate auslesen

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
EmaNymton
User
Beiträge: 174
Registriert: Sonntag 30. Mai 2010, 14:07

Hallo zusammen,
ich möchte gerne Fehlstunden von Schülern in einem dictionary verwalten, dass als keys das jeweilige Datum von Typ QDate enthält. Das ist soweit auch kein Problem, bei der Eingabe von den Fehlstunden werden diese in dem dictionary Fehlstunden gespeichert. Lasse ich mir das ganze z.B. für einen Schüler ausgeben, sieht es so aus:

Code: Alles auswählen

{PyQt4.QtCore.QDate(2010, 7, 31): 0, PyQt4.QtCore.QDate(2010, 7, 30): 1, PyQt4.QtCore.QDate(2010, 7, 27): 0}
Das sieht für mich eigentlich ok aus.

Mit folgendem Quelltext möchte ich die Schüler in einem QListWidget anzeigen lassen, um die Fehlstunden entschuldigen zu können.

Code: Alles auswählen

def fehlstundenAnzeigen(self):
	self.listWidget.clear()	
	for schueler in self.kurs.Teilnehmer:
		if self.datum in schueler.Fehlstunden:
			item = QtGui.QListWidgetItem()
			item.setText(schueler.Vorname + ' ' + schueler.Name)
			item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable)
			if schueler.istFehlstundeEntschuldigt(self.datum):
			   item.setCheckState(QtCore.Qt.Checked)
			else:
			   item.setCheckState(QtCore.Qt.Unchecked)
			self.listWidget.addItem(item)
self.datum ist dabei das ausgewählte Datum eines QCalendarWidget, also auch vom Typ QDate.

Die if-Abfrage wird aber überhaupt nicht durchlaufen. Wenn ich self.datum in schueler.Fehlstunden.keys() überprüfe durchläuft er die if-Abfrage, meckert allerdings dann beim Aufruf der Methode istFehlstundeEntschuldigt über einen KeyError:

Code: Alles auswählen

KeyError: PyQt4.QtCore.QDate(2010, 7, 31)
Die Methode istFehlstundeEntschuldigt in der Klasse Schueler sieht so aus:

Code: Alles auswählen

def istFehlstundeEntschuldigt(self,datum):
		if self.Fehlstunden[datum]==1:
			return True
		else:
			return False
Ich steh irgendwie aufm Schlauch und bitte um Hilfe!
Gruß EmaNymton
Zuletzt geändert von EmaNymton am Mittwoch 30. Juni 2010, 13:47, insgesamt 1-mal geändert.
BlackJack

@EmaNymton: `QDate` kann man nicht als Schlüssel in Dictionaries verwenden. Die `__hash__()`-Methode ist dafür anscheinend falsch implementiert:

Code: Alles auswählen

from PyQt4.QtCore import QDate

a = QDate(2010, 7, 31)
b = QDate(2010, 7, 31)

print a == b, hash(a) == hash(b)
Ergibt:

Code: Alles auswählen

True False
Gleiche Objekte die einen unterschiedlichen Hash-Wert ergeben sind irgendwie kaputt.

Die letzte Methode ist übrigens umständlicher formuliert als es sein müsste, denn der Ausdruck beim ``if`` wird ja schon zu einem Wahrheitswert ausgewertet:

Code: Alles auswählen

def ist_fehlstunde_entschuldigt(self, datum):
    return self.fehlstunden[datum] == 1
Nachtrag: Ich hoffe in dem Dictionary wird zu jedem Datum die Anzahl der Fehlstunden gespeichert und nicht 0 und 1 als Wahrheitswerte missbraucht.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Du kannst QDate ja eine hash-Methode anhand des Datums unterschieben:

Code: Alles auswählen

>>> from PyQt4.QtCore import QDate
>>> d={}
>>> d[QDate(2007, 1, 1)]=0
>>> QDate(2007, 1, 1) in d
False
>>> d[QDate(2007, 1, 1)]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: PyQt4.QtCore.QDate(2007, 1, 1)
>>> class MyDate(QDate):
...   def __hash__(self):
...     return self.day()+self.month()*100+self.year()*10000 # oder self.toPyDate().__hash__()
...
>>> d[MyDate(2007, 1, 1)]=0
>>> MyDate(2007, 1, 1) in d
True
>>> d[MyDate(2007, 1, 1)]
0
>>> hash(MyDate(2007, 1, 1))
20070101
lunar

Mit der API-Version 2 ist __hash__ für QDate korrekt implementiert. Diese Version ist Standard unter Python 3, für Python 2 muss sie explizit aktiviert werden:

Code: Alles auswählen

import sip
sip.setapi('QDate' 2)
Mehr dazu in der Dokumentation. Das Ganze funktioniert iirc seit PyQt 4.6.
EmaNymton
User
Beiträge: 174
Registriert: Sonntag 30. Mai 2010, 14:07

Vielen Dank an alle drei, mit lunars Hinweis funktionierts jetzt, es fehlte allerdings ein Komma ;)

Code: Alles auswählen

import sip
sip.setapi('QDate', 2)
Vielleicht war der Fehler auch absichtlich drin, damit ich nochmal in die Doku reinschaue ;)
Nachtrag: Ich hoffe in dem Dictionary wird zu jedem Datum die Anzahl der Fehlstunden gespeichert und nicht 0 und 1 als Wahrheitswerte missbraucht.
Öhm, natürlich nicht ;)
Ich weiß, dass das nicht sauber ist. Ist ne dumme Angewohnheit von mir, habe ich aber jetzt berichtigt und gelobe Besserung. ;)
lunar

@EmaNymton: Oh, verzeih mir den Fehler, das war natürlich keine Absicht :)
Antworten