Einer der in Python integrierten Typen ist das Diktat.
>>> d = {"zero": False, "one": True}
>>> d["zero"]
False
>>> d["one"]
True
>>> type(d)
<class 'dict'>
Wörterbücher sind Module, ohne sie explizit im Programm verwenden zu müssen
>>> type(__builtins__.__dict__)
<class 'dict'>
>>> import os
>>> type(os.__dict__)
<class 'dict'>
Und Klassenattribute
>>> class MyClass(object):
... def __init__(self):
... self.a = 1
...
>>> x = MyClass()
>>> x.__dict__
{'a': 1}
Es wird implizit an verschiedenen Stellen verwendet.
Wenn Sie es als Wörterbuchschlüssel angeben, kann ein Fehler auftreten. Zum Beispiel
>>> a = dict()
>>> type(a)
<class 'dict'>
>>> a[[0]] = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Wenn Sie versuchen, eine Liste als Wörterbuchschlüssel wie diesen zu verwenden, werden Sie wütend, weil es sich um einen nicht verwischbaren Typ handelt. Mal sehen, warum es solche Einschränkungen gibt.
https://ja.wikipedia.org/wiki/ハッシュ関数
Hash-Funktion(Hash-Funktion)Oder was ist eine Zusammenfassungsfunktion?
Eine Operation zum Erhalten eines numerischen Wertes, der die Daten darstellt, die bestimmten Daten gegeben sind, oder
Eine Funktion, um einen solchen numerischen Wert zu erhalten.
Die Bedeutung von "Darstellung von Daten" ist, dass der von der Hash-Funktion erhaltene Wert ist
a == b (a.__eq__(b) == True)Dann Hash(a) == hash(b) (a.__hash__() == b.__hash__())
Dass es sich trifft.
Im Wörterbuch werden Hash-Funktionen verwendet, um den Bedarf an kostengünstiger Verarbeitung zu decken und die gesamte Suche nach __eq__
beim Festlegen und Abrufen von Werten zu vermeiden.
`__eq__
→ FehlerIn der CPython-Dikt-Implementierung
__eq__``` → Vermeiden Sie die Kosten für
`eq```Es wurde entwickelt.
__hash__
Ist es hashbar, solange es eine Methode gibt? Laut Dokumentation
http://docs.python.jp/2.7/glossary.html#term-hashable
Hashbare Objekte haben Hash-Werte, die sich für den Rest ihres Lebens nicht ändern(__hash__()Benötigen Sie eine Methode)、...
Und es ist erforderlich, dass sich der Hash-Wert während der Lebensdauer nicht ändert. Dies ist jedoch im Allgemeinen nicht möglich, sodass die Implementierung der Wörterbuchwerteinstellung nur prüft, ob die Hash-Funktion aufgerufen werden kann.
Die Klassifizierung von eingebauten Objekten ist
Was hier in Hashable enthalten ist, garantiert jedoch, dass sich der Hashwert während der Lebensdauer nicht ändert. Aber was ist mit benutzerdefinierten Objekten?
http://docs.python.jp/2.7/reference/datamodel.html#object.hash
Die Klasse definiert veränderbare Objekte__cmp__()Oder__eq__()Methode
Wenn implementiert,__hash__()Darf nicht definiert werden. Dies ist ein Hash in der Wörterbuchimplementierung
Weil der Wert unveränderlich sein muss.(Wenn sich der Hashwert des Objekts ändert
Hash-Bucket mit dem falschen Schlüssel:Es wird im Hash-Eimer sein)。
Versuchen wir ein Beispiel, das die Schlüsseltypprüfung tatsächlich umgeht. Im folgenden Beispiel verfügt UnhashableInFact über eine Hash-Funktion, der Hash-Wert ändert sich jedoch während der Lebensdauer der Instanz.
wrong_bucket.py
# -*- coding: utf-8 -*-
class UnhashableInFact(object):
def __init__(self, n):
self.n = n
def __hash__(self):
return hash(self.n)
def __eq__(self, other):
return self.n == other.n
if __name__ == '__main__':
a = UnhashableInFact(1)
b = UnhashableInFact(2)
mydict = {a: "value for 1", b: "value for 2"}
print(mydict[a], mydict[b]) # (1)
a.n = 2 #→ Hash-Wert ändert sich
print(mydict[a], mydict[b]) # (2)
c = UnhashableInFact(1)
print(c in mydict) # (3)
Wenn dies ausgeführt wird, ist das Verhalten wie folgt.
% python wrong_bucket.py
('value for 1', 'value for 2') # (1)Sie können den Wert aus jedem Bucket abrufen
('value for 2', 'value for 2') # (2)Beide"value for 2"Wird herausnehmen
False # (3)Auch wenn Sie etwas bringen, das dem Originalschlüssel entspricht"value for 1"Kann nicht herausgenommen werden
Warum hat es sich so verhalten? Der Eintrag im Wörterbuch ist
cpython/Include/dictobject.h
typedef struct {
/* Cached hash code of me_key. Note that hash codes are C longs.
* We have to use Py_ssize_t instead because dict_popitem() abuses
* me_hash to hold a search finger.
*/
Py_ssize_t me_hash;
PyObject *me_key;
PyObject *me_value;
} PyDictEntry;
Es ist geworden
http://docs.python.jp/2.7/reference/datamodel.html#object.hash
Aus der Elternklasse__hash__()Erben Sie die Methode,__cmp__()Oder__eq__()Bedeutung von
Ändern(Zum Beispiel Wechsel von wertbasierter Äquivalenz zu identitätsbasierter Äquivalenz)
Da der Hashwert der Klasse nicht mehr gültig ist__hash__ =Schreiben Sie None in die Klassendefinition
Sie können ausdrücklich erklären, dass es nicht hashbar ist.
Lass es uns versuchen.
unhashable.py
class Unhashable(object):
__hash__ = None
def __init__(self, n):
self.n = n
def __eq__(self, other):
return self.n == other.n
if __name__ == '__main__':
a = Unhashable(1)
{a: "value for 1"}
Auf diese Weise können Sie es abspielen, wenn Sie es als Wörterbuchschlüssel verwenden:
% python unhashable.py
Traceback (most recent call last):
File "unhashable.py", line 13, in <module>
{a: "value for 1"}
TypeError: unhashable type: 'Unhashable'
Wenn Sie in Python3 `` `eq``` überschreiben, wird es automatisch auf None gesetzt.
http://docs.python.jp/3/reference/datamodel.html#object.hash
__eq__()Überschreiben__hash__()Nicht definierte Klassen sind implizit
Wurde auf Keine gesetzt__hash__()Haben. Klasse__hash__()Die Methode ist
Wenn Keine, sollten Sie versuchen, den Hashwert einer Instanz dieser Klasse abzurufen
TypeError wird ausgelöst und isinstance(obj, collections.Hashable)prüfen
Dann wird es korrekt als nicht hashbar erkannt.
http://docs.python.jp/2.7/glossary.html#term-immutable
Ein Objekt mit einem festen Wert. Unveränderliche Objekte umfassen Zahlen, Zeichenfolgen,
Und Tupel und so weiter. Die Werte dieser Objekte können nicht geändert werden. Ein weiterer Wert
Sie müssen ein neues Objekt erstellen, um sich zu erinnern.
Unveränderliche Objekte spielen eine wichtige Rolle in Situationen, in denen feste Hashwerte erforderlich sind.
Ein Beispiel ist ein Schlüssel in einem Wörterbuch.
Schlüssel in Wörterbüchern werden als unveränderliche Verwendung erwähnt.
Recommended Posts