【问题标题】:Why is this python class instance hashable?为什么这个 python 类实例是可散列的?
【发布时间】:2017-09-14 22:36:25
【问题描述】:

这与 python 2.x 相关

在下面的类中,如果我们将“object”子类化,我知道这些方法是在派生类 Foo 中继承的,其中包括__hash__(可以通过打印目录(Foo())

因此调用 hash(Foo()) 调用魔术方法 __hash__ 并给我们一个哈希值。

但是,如果我们不继承“object”,导致 dir(Foo()) 没有列出 __hash__ 方法,那为什么要我们仍然在 python2 中得到一个哈希值?

我相信在 python3 中这个问题已经得到解决,因为来自 "object*" 类的方法是默认继承的。

#class Foo(object) Works since __hash__ is available in the base class 
class Foo:  #Why does this work? 
    def __init__(self):
        self.x = None
a = Foo()
print dir(a) # No __hash__ magic method
print hash(a) 
# Expecting an error like non-hashable or __hash__ not implemented 
# or something similar

【问题讨论】:

标签: python python-2.7 oop hash python-2.x


【解决方案1】:

老式的类很奇怪。正式地,旧式类的实例并不完全是其类的实例,它们都是instance 类型的实例。 The instance type defines __hash__tp_hash 是 C 级插槽,对于 C 定义的类型等效于 __hash__),因此即使它没有直接在您的实例上定义,也没有在创建它的类上定义,它在instance 通过奇怪而可怕的魔法输入自己(实际上,魔法在于它如何设法使用你的类的功能,因为它的类型是 instance)。

您可以在交互式解释器中看到这一点:

>>> class Foo: pass

>>> Foo().__hash__  # Same basic error for Foo.__hash__ too
AttributeError                            Traceback (most recent call last)
...
----> 1 Foo().__hash__

AttributeError: Foo instance has no attribute '__hash__'
>>> type(Foo())
<type 'instance'>
>>> type(Foo()).__hash__
<slot wrapper '__hash__' of 'instance' objects>

即使实例本身看不到__hash__,这仍然有效,因为“特殊方法”(那些以双下划线开头和结尾的特殊方法)是在类型而不是实例上查找的,所以__hash__可以在 instance 上找到。在 C 级别,hash(x) is doing the equivalent of type(x).__hash__(x)(它有点复杂,因为如果 __eq__ 有自定义定义,它不会使用默认的 __hash__ 实现,但这是一般的想法)。

【讨论】:

  • 很好的答案!谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多