【问题标题】:__hash__ method and documentation. Probable error?__hash__ 方法和文档。可能的错误?
【发布时间】:2014-06-16 16:27:51
【问题描述】:

阅读文档

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 对象上调用散列函数?

【问题讨论】:

  • 散列集合的成员,然后是散列集合的示例。 setfrozensetdict 是散列集合,而不是此类散列集合的成员。文档告诉你 hash() 在这里 for 的用途。

标签: python python-3.x dictionary


【解决方案1】:

由内置函数 hash() 调用,用于对散列集合的 成员 进行操作,包括 set、frozenset 和 dict。 [...]

__hash__ 在集合成员(或键)上调用,而不是在集合本身上。

【讨论】:

  • 我不明白,如果我这样做 hash(a.keys()) 我总是得到同样的不可散列的错误......
  • @antox: a.keys() 返回一个列表。在个人键上调用hash()
  • 在python3中它返回一个dict_keys对象
  • @antox:当然,同样的区别。 listdict_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__ 方法。

【讨论】:

  • 再问一个问题,如果 dicts、lists 等不可散列,为什么要定义 hash 方法?
  • @antox:表示它们不可散列。他们没有__hash__ 方法;他们将属性设置为None。请参阅object.__hash__ documentation... 可以通过在类定义中设置 __hash__ = None 来明确地将自己标记为不可散列。
  • @antox:在C代码中,PyObject_HashNotImplemented用于tp_hash slot;它会引发TypeError 来标记对象不可散列。
猜你喜欢
  • 2017-03-18
  • 2016-11-20
  • 2017-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-11
相关资源
最近更新 更多