2012-01-25 14 views
20

Robiłem rozmyślania nad parserem wiersza poleceń i zastanawiałem się, jakiego rodzaju algorytmu hashowego używa python dict?Jaki algorytm mieszania używa mapowanie słownika Pythona?

Sposób, w jaki mam to ustawić, Mam algorytm dopasowywania wzorców, który dopasowuje tokenizowane sekwencje wejściowe za pomocą klucza słownika. Niektóre klucze są stosunkowo długie (długość 5 lub 6 krotności po 6-7 ciągów znaków). Zastanawiałem się, czy istnieje punkt, w którym długie klawisze słownika znacznie zmniejszają wydajność kluczowego wyszukiwania.

+1

Spójrz na [Objects/dictnotes.txt] (http://hg.python.org/cpython/file/2.7/Objects/dictnotes.txt) – jfs

+1

Spójrz na [to pytanie] (http://stackoverflow.com/questions/ 2070276/where-can-i-find-source-or-algorithm-of-pythons-hash-function). Ma link do [tej strony] (http://effbot.org/zone/python-hash.htm), który opisuje, w jaki sposób Python miesza różne typy i może ci się przydać. – srgerg

Odpowiedz

23

Wartość skrótu, której używa, zależy od obiektu, który jest używany jako klucz - każda klasa może zdefiniować własną metodę __hash __(), a wartość zwracana dla konkretnej instancji jest używana w słowniku.

Sam Python zapewnia implementację skrótu dla typów str i tuple. Szybkie spojrzenie na źródło powinno ujawnić dokładny algorytm dla nich.

Mieszanie krotki opiera się na hashach jego zawartości. Algorytm jest zasadniczo ten (uproszczona nieznacznie):

def hash(tuple): 
    mult = 1000003 
    x = 0x345678 
    for index, item in enumerate(tuple): 
     x = ((x^hash(item)) * mult) & (1<<32) 
     mult += (82520 + (len(tuple)-index)*2) 
    return x + 97531 

Na strunach, interpreter także iteracje nad każdej postaci, łącząc je z tym (znowu, nieco uproszczony) Algorytm:

def hash(string): 
    x = string[0] << 7 
    for chr in string[1:]: 
     x = ((1000003 * x)^chr) & (1<<32) 
    return x 

Większym problemem martwić się unikaniem kolizji hash. Colliding hash keys spowoduje przeszukiwanie liniowe, ponieważ słownik próbuje znaleźć miejsce do przechowywania nowego obiektu (jest to obecnie rozpoznawane jako problem bezpieczeństwa, a zachowanie może się zmieniać w nadchodzących wersjach pythona)

+0

Oh ok. Z jakiegoś powodu założyłem, że Python użył ogólnego algorytmu mieszania bajtów dla wszystkich typów danych. Jeśli chodzi o zderzanie kluczy hash, nie sądzę, że to będzie problem, ponieważ liczba kluczy, które będę mieć, jest (stosunkowo) mała - prawdopodobnie w tysiącach. Wybacz mi moją hochsztaplerię, ale w jaki sposób kolidujące hashy i liniowe wyszukiwania stają się problemem bezpieczeństwa? –

+2

@Joel Cornett: Jest to problem związany z bezpieczeństwem, ponieważ tabele mieszania używają segmentów do przechowywania kluczy, a klucze o tym samym haszowaniu są mieszane do tego samego segmentu, zmuszając tabelę mieszającą do wykonania liniowego wyszukiwania za każdym razem, gdy szuka klucz, który może być bardzo nieefektywny (a nawet może spowodować odmowę usługi), jeśli liczba kluczy jest duża. Ataki typu Denial-of-Service mogą wystąpić, jeśli program napotka tablicę asocjacyjną z różnymi kluczami, które będą mieszały się z tym samym kodem mieszającym. –

+0

Jeśli atakujący może kontrolować klucze używane w słowniku, to może być w stanie wstawić setki lub tysiące zderzających się kluczy, przez co operacje wstawiania będą bardzo powolne. W niektórych przypadkach może to spowodować, że komputer przestanie reagować lub baza danych stanie się bezużyteczna - atak Dos –

Powiązane problemy