Hash-bare Riesenobjekte??

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
Goswin
User
Beiträge: 363
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen
Kontaktdaten:

Ich habe überhaupt keinen Durchblick, welche Objekte hash-bar sind und welche nicht. Falls ich

Code: Alles auswählen

class gesamte_galaxie(object):
  #Milliarden Attribute und Methoden
  pass
galaxie = gesamte_galaxie()
definiere, dann ist galaxie ohne weiteres hash-bar und als Key in einem Dictionary zu gebrauchen. Anscheinend kann ich die Klasse gesamte_galaxie so komplex gestalten wie ich will, sie BLEIBT hash-bar. Wenn ich aber

Code: Alles auswählen

paar = laecherliches_paar = list([1,2])
definiere, dann ist das auf einmal NICHT hash-bar. Was geht hier vor?
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

Hallo Goswin,

ja, Listen sind nicht hashbar. Warum? Wird wohl was mit ihrer Komplexitaet zu tun haben. Tuples sind aber zB hashbar...

Uebrigens sollte man Klassen-Namen in CamelCase schreiben ;)
[url=http://www.python-forum.de/post-86552.html]~ Wahnsinn ist auch nur eine andere Form der Intelligenz ~[/url]
hackerkey://v4sw6CYUShw5pr7Uck3ma3/4u7LNw2/3TXGm5l6+GSOarch/i2e6+t2b9GOen7g5RAPa2XsMr2
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hallo!

Vielleicht kann der erste Absatz dieser Seite http://docs.python.org/lib/typesmapping.html ein wenig Licht ins Dunkel bringen.

EDIT:

Das auch noch: http://docs.python.org/lib/built-in-funcs.html#l2h-36

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
BlackJack

Und die Standard-`__hash__()`-Implementierung von Objekten basiert einfach auf der Objektidentität. Dabei ist es also egal wie "gross" das Objekt ist, die Identität bleibt immer gleich und auch gleich "gross".
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

nkoehring hat geschrieben:ja, Listen sind nicht hashbar. Warum? Wird wohl was mit ihrer Komplexitaet zu tun haben. Tuples sind aber zB hashbar...
Tuples sind auch immutable. Listen würden ihren Hash ändern, wenn man Items hinzufügt.
TUFKAB – the user formerly known as blackbird
Benutzeravatar
Goswin
User
Beiträge: 363
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen
Kontaktdaten:

Zusatz an Blackjack:

Ich habe in meinem Programm naiverweise Klasseninstanzen als Keys benutzt und KEINE FEHLERMELDUNGEN erhalten. Nun stimmen aber die Ergebnisse nicht, und ich frage mich, ob wegen meiner Key-Verwendung durchaus Fehler entstehen, die aber nicht angezeigt werden.

Im Buch Learning Python, von Lutz & Ascher, heißt es auf Seite 108:
Class instance objects can be used as keys too, as long as they have the proper protocol methods; they need to to tell Python that their value won't change.
Leider wird nicht erklärt, was Protocol methods sind und wie man "Python sagt, dass sich Objekte nicht verändern", Vielleicht gelten diese Einschränkungen auch nur für old-style classes, die in diesem Buch noch einen relativ hohen Stellenwert haben.

Und dann bleibt natürlich noch die Frage, warum (zum Beispiel) Listen nicht ebenfalls anhand ihrer Objekt-Identität gehasht werden. Sind Listen etwa nicht ehrenwerte (first-class) Objekte? Aber ich setze einmal voraus, dass das historisch so gewachsen ist, weil niemand damals auf diese Idee gekommen ist...
BlackJack

Wie gesagt werden bei Objekten erst einmal die Identitäten für den Hash-Wert heran gezogen. Und Vergleiche mit ``==`` und ``!=`` arbeiten auch per Vorgabe erst einmal mit der Objektidentität.

Für Dictionaries wichtig ist, dass diese beiden immer zusammen passen und dass sich der Hash-Wert nicht ändern kann. Zusammenpassen heisst, wenn ``obj1 == obj2`` gilt, dann muss auch ``hash(obj1) == hash(obj2)`` gelten. Wenn Du bei Deinen Klassen also ``__cmp__``, oder ``__eq__``, ``__ne__`` implementierst, musst Du das auch mit ``__hash__`` tun, und zwar so, dass die besagte Bedingung erfüllt ist.

Wenn Du solche Objekte als Schlüssel in Dictionaries verwenden willst, darf sich der Hash nicht durch irgendwelche Operationen verändern, weil die Schlüssel sonst nicht wieder gefunden werden können.

Bei `list` ist der Vergleich vom Listeninhalt abhängig, d.h. der Hashwert würde sich ändern, wenn man die Liste verändert. Deswegen haben die Python-Entwickler vorsichts halber die `__hash__()`-Methode so überschrieben, dass sie unbedingt eine Ausnahme auslöst, die sagt, dass Listen nicht "hashable" sind.
Antworten