__hash__ метод и документация. Вероятная ошибка?

#python #python-3.x #dictionary

#python #python-3.x #словарь

Вопрос:

Чтение документа

object.__hash__(self)

Вызывается встроенной функцией hash() и для операций с элементами хешированных коллекций, включая set, frozenset и dict . […]

и….

Все неизменяемые встроенные объекты Python являются хешируемыми, в то время как изменяемые контейнеры (такие как списки или словари) отсутствуют.

Из консоли:

 >>> a = {'name': 'abcdef'}
>>> hash(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
  

Под этим я понимаю, что объект dict не является хешируемым, так почему в документе говорится, что я могу вызвать хеш-функцию для объекта dict?

Комментарии:

1. члены хешированных коллекций, за которыми следуют примеры хешированных коллекций. set , frozenset и dict являются хешированными коллекциями, а не членами таких хешированных коллекций. В документации указано, hash() для чего здесь используется.

Ответ №1:

Вызывается встроенной функцией hash() и для операций с элементами хешированных коллекций, включая set, frozenset и dict . […]

__hash__ вызывается для членов коллекции (или ключей), а не для самих коллекций.

Комментарии:

1. Я не понимаю, если я это делаю hash(a.keys()) , я всегда получаю одну и ту же нехешируемую ошибку…

2. @antox: a.keys() возвращает список. Вызов hash() отдельных ключей.

3. в python3 он возвращает объект dict_keys

4. @antox: конечно, та же разница. Ни a list , ни a dict_keys не являются тем, что хэшируется. Хэшируются отдельные ключи .

Ответ №2:

Вы неправильно читаете документацию.

object.__hash__ [c] поддерживается встроенной функцией hash() и для операций с элементами хешированных коллекций, включая set, frozenset и dict .

__hash__ не вызывается dict . Он вызывается для членов dict .

ДЕМОНСТРАЦИЯ:

 >>> class Hashable(object):
...     def __hash__(self):
...         print '__hash__ was called'
...         return super(Hashable, self).__hash__()
... 
>>> {Hashable(): None}
__hash__ was called
{<__main__.Hashable object at 0x10bce7750>: None}
  

Поскольку Hashable() экземпляр используется в качестве ключа, его __hash__ метод вызывается при создании словаря.

Комментарии:

1. Еще один вопрос: если dicts, списки и т. Д. Не Являются хешируемыми, Почему они определяют метод хеширования ?

2. @antox: сигнализировать, что они не являются хешируемыми. У них нет __hash__ метода; вместо этого у них установлен атрибут None . Смотрите object.__hash__ Документацию : … могут явно помечать себя как недоступные для хэширования, задав __hash__ = None в определении класса.

3. @antox: в коде C PyObject_HashNotImplemented используется для tp_hash слота ; он вызывает a TypeError , чтобы отметить, что объект не является хешируемым.