Я спробував шукати Інтернет, але не зміг знайти значення хешируемого.
Коли кажуть, що об’єкти є hashable
чи hashable objects
що це означає?
Я спробував шукати Інтернет, але не зміг знайти значення хешируемого.
Коли кажуть, що об’єкти є hashable
чи hashable objects
що це означає?
Відповіді:
З словника Python :
Об'єкт є хешируемим, якщо він має хеш-значення, яке ніколи не змінюється протягом свого життя (йому потрібен
__hash__()
метод), і його можна порівняти з іншими об'єктами (йому потрібен__eq__()
або__cmp__()
метод). Об'ємні об'єкти, які порівнюють рівні, повинні мати однакове хеш-значення.Можливість використання об'єкта використовується як ключ словника та набір елементів, оскільки ці структури даних використовують хеш-значення всередині.
Усі незмінні вбудовані об'єкти Python є хедж-енд, а змінні контейнери (наприклад, списки чи словники) не є. Об'єкти, які є примірниками визначених користувачем класів, за замовчуванням є хешируемими; всі вони порівнюють нерівні, і хеш-цінність їхня
id()
.
hash value
зараз те, що має хеш-значення. ви можете навести приклад
__hash__()
. Більш загально див. En.wikipedia.org/wiki/Hash_function
id(object)
16x результат object.__hash__()
. Отже, уривок глосарію для цієї версії невірний - хеш-значення немає id()
, але воно походить від нього (як це справді зазначалося в оновлених документах для python 2.7.12).
hash((1, [2, 3]))
побачити це в дії. Я опублікував запит на виправлення запису з глосарію на предмет хешавання.
У всіх відповідях тут є чітке робоче пояснення хешируемих об'єктів у python, але я вважаю, що потрібно спершу зрозуміти термін Хешинг.
Хешинг - це концепція в галузі інформатики, яка використовується для створення високопродуктивних, псевдоструктур даних з випадковим доступом, де потрібно швидко зберігати та отримувати доступ до них.
Наприклад, якщо у вас є 10 000 номерів телефонів, і ви хочете зберігати їх у масиві (це послідовна структура даних, яка зберігає дані у суміжних місцях пам'яті та забезпечує випадковий доступ), але у вас може не бути необхідної суміжної кількості місця пам'яті.
Отже, ви можете замість цього використовувати масив розміром 100 та використовувати хеш-функцію для набору набору значень для тих самих індексів, і ці значення можуть зберігатися у пов'язаному списку. Це забезпечує продуктивність, схожу на масив.
Тепер хеш-функція може бути такою ж простою, як ділення числа на розмір масиву та взяття залишку як індекс.
Більш детально див. Https://en.wikipedia.org/wiki/Hash_function
Ось ще одна хороша довідка: http://interactivepython.org/runestone/static/pythonds/SortSearch/Hashing.html
Все, що не змінюється (засоби, що змінюються, можливо, зміниться), може бути хешировано. Крім хеш-функції, яку потрібно шукати, якщо клас має, наприклад, dir(tuple)
і шукаючи __hash__
метод, ось кілька прикладів
#x = hash(set([1,2])) #set unhashable
x = hash(frozenset([1,2])) #hashable
#x = hash(([1,2], [2,3])) #tuple of mutable objects, unhashable
x = hash((1,2,3)) #tuple of immutable objects, hashable
#x = hash()
#x = hash({1,2}) #list of mutable objects, unhashable
#x = hash([1,2,3]) #list of immutable objects, unhashable
Перелік незмінних типів:
int, float, decimal, complex, bool, string, tuple, range, frozenset, bytes
Список типів, що змінюються:
list, dict, set, bytearray, user-defined classes
Ellipsis
це також непорушний тип і може бути використаний як ключ до dict
.
hash(MyClass)
__hash__
та __eq__
. Більше того, усі визначені користувачем класи реалізують ці методи (і, таким чином, є доступними), тому що вони успадковують методи від object
(універсальний базовий клас).
Наскільки я розумію згідно з глосарієм Python, коли ви створюєте екземпляр об'єктів, які є хешируемими, незмінне значення також обчислюється відповідно до членів або значень екземпляра. Наприклад, це значення може бути використане як ключ у диктаті, як показано нижче:
>>> tuple_a = (1,2,3)
>>> tuple_a.__hash__()
2528502973977326415
>>> tuple_b = (2,3,4)
>>> tuple_b.__hash__()
3789705017596477050
>>> tuple_c = (1,2,3)
>>> tuple_c.__hash__()
2528502973977326415
>>> id(a) == id(c) # a and c same object?
False
>>> a.__hash__() == c.__hash__() # a and c same value?
True
>>> dict_a = {}
>>> dict_a[tuple_a] = 'hiahia'
>>> dict_a[tuple_c]
'hiahia'
ми можемо виявити, що значення хеша tuple_a і tuple_c однакові, оскільки вони мають однакові члени. Коли ми використовуємо tuple_a як ключ у dict_a, ми можемо виявити, що значення для dict_a [tuple_c] є однаковим, це означає, що коли вони використовуються як ключ у dict, вони повертають те саме значення, оскільки хеш-значення так само. Для тих об'єктів, які не є хешируемими, метод хеша визначається як None:
>>> type(dict.__hash__)
<class 'NoneType'>
Я думаю, що це хеш-значення обчислюється після ініціалізації екземпляра, а не динамічним способом, саме тому хешируемие можуть бути лише незмінні об'єкти. Сподіваюся, це допомагає.
Дозвольте навести вам робочий приклад для розуміння хешируемих об'єктів у python. Я беру для цього прикладу 2 кортежі. Кожне значення кортежа має унікальне значення хеша, яке ніколи не змінюється протягом свого життя. Тож виходячи з цього має значення, робиться порівняння двох кортежів. Ми можемо отримати хеш-значення елемента кортежа за допомогою id ().
У python це означає, що об'єкт може бути членами наборів для повернення індексу. Тобто вони мають унікальну особу / ідентифікатор.
наприклад, у python 3.3:
Структура даних Списки не є доступними, але структура даних Tuples є хешируемой.
id
, що (приблизно) адреса об'єкта в пам'яті.
Гашебний = здатний хешировать.
Гаразд, що хеш? Хеш-функція - це функція, яка приймає об'єкт, наприклад, рядок типу "Python", і повертає код фіксованого розміру. Для простоти припустимо, що повернене значення є цілим числом.
Коли я запускаю хеш ("Python") в Python 3, я отримую 5952713340227947791 як результат. Різні версії Python можуть змінювати основні хеш-функції, тому ви, ймовірно, отримаєте інше значення. Важливо те, що незалежно від того, багато разів я запускаю хеш ("Python"), я завжди отримуватиму однаковий результат із тією ж версією Python.
Але хеш ("Java") повертає 1753925553814008565. Отже, якщо об'єкт, який я хешую, зміниться, то і результат. З іншого боку, якщо об'єкт, який я хешую, не зміниться, результат залишається таким же.
Чому це має значення?
Ну, наприклад, словники Python вимагають, щоб ключі були незмінними. Тобто, ключі повинні бути об'єктами, які не змінюються. Струни незмінні в Python, як і інші основні типи (int, float, bool). Кортежі та фрозенсети також непорушні. Списки, з іншого боку, не є незмінними (тобто вони є змінними), оскільки ви можете їх змінити. Аналогічно, дикти змінюються.
Тож, коли ми говоримо, що щось є грішним, ми маємо на увазі, що це незмінне. Якщо я спробую передати змінний тип функції хеш (), це не вдасться:
>>> hash('Python')
1687380313081734297
>>> hash('Java')
1753925553814008565
>>>
>>> hash([1, 2])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash({1, 2})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'
>>> hash({1 : 2})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>>
>>> hash(frozenset({1, 2}))
-1834016341293975159
>>> hash((1, 2))
3713081631934410656
У Python будь-який незмінний об'єкт (такий як ціле число, булева, рядок, кортеж) є придатним для зміни, тобто його значення не змінюється протягом його життя. Це дозволяє Python створювати унікальне хеш-значення для його ідентифікації, яке може використовуватися словниками для відстеження унікальних ключів та наборів для відстеження унікальних значень.
Ось чому Python вимагає від нас використовувати незмінні типи даних для ключів у словнику.
Для створення таблиці хешування з нуля всі значення повинні бути встановлені на "None" та змінені, коли виникає вимога. Об'ємні об'єкти відносяться до модифікованих типів даних (Словник, списки тощо). Набори з іншого боку не можуть бути повторно ініціалізовані, коли їх присвоєно, тому набори не підлягають перегляду. Тоді як варіант set () - Заморожений набір () - є хешируемим.
__hash__()
методу .