Hashbar in Python

Das Ziel dieser Geschichte

Wörterbuch

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.

Geben Sie error ein, wenn Sie ein Wörterbuch verwenden

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.

Was ist Hash?

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.

Bedeutung der Hash-Funktion im Wörterbuch

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.

In der CPython-Dikt-Implementierung

Es wurde entwickelt.

Ist es hashbar, wenn es eine `` hash``` Methode gibt?

__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?

Für benutzerdefinierte Objekte

nicht zerlegbarer Schlüssel

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

Zu erklären, dass es nicht zerlegbar ist

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.

hashable und unveränderlich

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.

Zusammenfassung

Recommended Posts

Hashbar in Python
Quadtree in Python --2
Python in der Optimierung
CURL in Python
Metaprogrammierung mit Python
Python 3.3 mit Anaconda
SendKeys in Python
Epoche in Python
Zwietracht in Python
Deutsch in Python
DCI in Python
Quicksort in Python
nCr in Python
N-Gramm in Python
Programmieren mit Python
Konstante in Python
FizzBuzz in Python
SQLite in Python
Schritt AIC in Python
LINE-Bot [0] in Python
CSV in Python
Reverse Assembler mit Python
Reflexion in Python
Konstante in Python
nCr in Python.
Scons in Python 3
Puyopuyo in Python
Python in Virtualenv
PPAP in Python
Quad-Tree in Python
Reflexion in Python
Chemie mit Python
DirectLiNGAM in Python
LiNGAM in Python
In Python reduzieren
In Python flach drücken
Sortierte Liste in Python
Täglicher AtCoder # 36 mit Python
Clustertext in Python
AtCoder # 2 jeden Tag mit Python
Täglicher AtCoder # 32 in Python
Täglicher AtCoder # 6 in Python
Täglicher AtCoder # 18 in Python
Bearbeiten Sie Schriftarten in Python
Singleton-Muster in Python
Dateioperationen in Python
Lesen Sie DXF mit Python
Täglicher AtCoder # 53 in Python
Tastenanschlag in Python
Verwenden Sie config.ini mit Python
Täglicher AtCoder # 33 in Python
Löse ABC168D in Python
Logistische Verteilung in Python
Täglicher AtCoder # 7 in Python
LU-Zerlegung in Python
Einfacher gRPC in Python
AtCoder # 24 jeden Tag mit Python
Löse ABC167-D mit Python