sha3 - python hash()




Warum und wie funktionieren Python-Funktionen? (2)

Ich habe kürzlich die folgenden Befehle in Python ausprobiert:

>>> {lambda x: 1: 'a'}
{<function __main__.<lambda>>: 'a'}

>>> def p(x): return 1
>>> {p: 'a'}
{<function __main__.p>: 'a'}

Der Erfolg beider dict Kreationen zeigt, dass sowohl Lambda als auch reguläre Funktionen hashbar sind. (Etwas wie {[]: 'a'} schlägt mit TypeError: unhashable type: 'list' fehl TypeError: unhashable type: 'list' ).

Der Hash ist offensichtlich nicht unbedingt die ID der Funktion:

>>> m = lambda x: 1
>>> id(m)
140643045241584
>>> hash(m)
8790190327599
>>> m.__hash__()
8790190327599

Der letzte Befehl zeigt, dass die Methode __hash__ explizit für lambda s definiert ist, dh dass dies keine automatische Sache ist, die Python basierend auf dem Typ berechnet.

Was ist die Motivation, Funktionen funktionsfähig zu machen? Für einen Bonus, was ist der Hash einer Funktion?


Eine Funktion ist hashbar, weil sie ein normales, eingebautes, nicht veränderbares Objekt ist.

Aus dem Python-Handbuch :

Ein Objekt ist hashbar, wenn es einen Hash-Wert hat, der sich während seiner Lebensdauer niemals ändert (es benötigt eine __hash__() -Methode) und mit anderen Objekten verglichen werden kann (es benötigt eine __eq__() oder __cmp__() -Methode). Hash-Objekte, die gleich sind, müssen denselben Hash-Wert haben.

Durch die Hashabibilität wird ein Objekt als Dictionary-Schlüssel und Set-Member nutzbar, da diese Datenstrukturen intern den Hash-Wert verwenden.

Alle unveränderlichen integrierten Objekte von Python sind hashbar, während keine veränderbaren Container (wie Listen oder Wörterbücher) vorhanden sind. Objekte, die Instanzen von benutzerdefinierten Klassen sind, sind standardmäßig hashbar. sie vergleichen alle ungleich (außer mit sich selbst), und ihr Hash-Wert wird von ihrer id() .


Es ist nichts Besonderes. Wie Sie sehen können, wenn Sie die ungebundene __hash__ Methode des Funktionstyps untersuchen:

>>> def f(): pass
...
>>> type(f).__hash__
<slot wrapper '__hash__' of 'object' objects>

Der of 'object' objects __hash__ bedeutet, dass er nur das standardmäßige identitätsbasierte __hash__ von object erbt. Funktion == und hash Arbeit nach Identität. Der Unterschied zwischen id und hash ist normal für jeden Typ, der das object.__hash__ erbt object.__hash__ :

>>> x = object()
>>> id(x)
40145072L
>>> hash(x)
2509067

Sie könnten denken, __hash__ soll nur für unveränderliche Objekte definiert werden, und Sie hätten fast recht, aber es fehlt ein Schlüsseldetail. __hash__ sollte nur für Objekte definiert werden, bei denen alles, was an == Vergleichen beteiligt ist, unveränderlich ist. Für Objekte, deren == auf Identität basiert, ist es völlig normal, hash auf Identität zu basieren, da selbst wenn die Objekte veränderbar sind, sie unmöglich so veränderbar sein können, dass sich ihre Identität ändert. Dateien, Module und andere veränderbare Objekte mit identitätsbasiertem == Alle verhalten sich so.





hash