简体   繁体   English

为什么这个python类实例可以清除?

[英]Why is this python class instance hashable?

This is pertaining to python 2.x 这与python 2.x有关

In the following class, if we subclass " object ", I understand the methods are inherited in the derived class Foo which includes __hash__ (can see this by printing dir(Foo() ) 在下面的类中,如果我们继承“ object ”,我理解这些方法是在包含__hash__的派生类Foo中继承的(可以通过__hash__ dir(Foo())看到这个

Hence calling hash(Foo()) calls the magic method __hash__ and gives us a hash value. 因此调用hash(Foo())调用魔术方法__hash__并给我们一个哈希值。

However, if we don't subclass " object ", resulting in dir(Foo()) not listing out the __hash__ method, so then why do we still get a hash value in python2? 但是,如果我们没有子类“ object ”,导致dir(Foo())没有列出__hash__方法,那么为什么我们仍然在python2中得到一个哈希值?

I believe in python3 this problem has been addressed since the methods from the 我相信python3这个问题已经解决了以来的方法 "object*" class are inherited by default. 默认情况下, “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

Old-style classes are weird. 旧式的课很奇怪。 Officially, instances of old-style classes aren't wholly instances of their class, they're all instances of type instance . 正式地说,旧式类的实例并不是它们类的完全实例,它们都是类型instance The instance type defines __hash__ ( tp_hash is the C level slot that's equivalent to __hash__ for C defined types), so even though it's not defined on your instance directly, nor on the class that created it, it finds __hash__ on the instance type itself through weird and terrible magic (actually, the magic is in how it manages to use your class's features at all, given that its type is instance ). instance类型定义了__hash__tp_hash是C级槽,相当于C定义类型的__hash__ ),所以即使它没有直接在你的实例上定义,也没有在创建它的类上定义,它通过instance类型自身找到__hash__奇怪而可怕的魔法(实际上,神奇的是它如何设法使用你的类的功能,因为它的类型是instance )。

You can see this in the interactive interpreter: 您可以在交互式解释器中看到:

>>> 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>

This works even though the instance itself can't see __hash__ because "special methods" (those documented special methods that begin and end with double underscores) are looked up on the type, not the instance, so __hash__ is found on instance itself. 即使实例本身看不到__hash__这也__hash__因为“特殊方法”(那些以双下划线开头和结尾的特殊方法)会在类型而不是实例上查找,因此在instance本身上可以找到__hash__ At the C level, hash(x) is doing the equivalent of type(x).__hash__(x) (it's a little more complicated because it won't use the default __hash__ implementation if __eq__ has a custom definition, but that's the general idea). 在C级别, hash(x)正在执行type(x).__hash__(x) (它有点复杂,因为如果__eq__有自定义定义它不会使用默认的__hash__实现,但这是一般的理念)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM