继承-__hash__在子类中设置为None [英] Inheritance - __hash__ sets to None in a subclass

查看:115
本文介绍了继承-__hash__在子类中设置为None的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我设法在Python 3.4和3.7上重现了这一点.

I managed to reproduce this on both Python 3.4 and 3.7.

考虑:

class Comparable:
    def _key(self):
        raise NotImplementedError

    def __hash__(self):
        return hash(self._key())

    def __eq__(self, other):
        ...

    def __lt__(self, other):
        ...


class A(Comparable): pass

class B(A):
    def __str__(self):
        return "d"

    def __eq__(self, other):
        return isinstance(self, type(other))

    def _key(self):
        return str(self),

b = B()

很显然,人们希望在这里定义b.__hash__,因为它是在Comparable下定义的,而B是其子类.

Clearly one would expect b.__hash__ to be defined here, since it is defined under Comparable which B is a subclass of.

Lo并已定义,但计算结果为None.有什么作用?

Lo and behold, it is defined, but evaluates to None. What gives?

>> b
<__main__.B object at 0x00000183C9734978>
>> '__hash__' in dir(b)
True
>> b.__hash__

>> b.__hash__ is None
True
>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <class '__main__.Comparable'>, <class 'object'>)
>> isinstance(b, Comparable)
True

如果在ComparableA中将__init__实现为super().__init__(),则会再现相同的行为.

The same behavior is reproduced if implementing __init__ as super().__init__() in Comparable and A.

推荐答案

重写__eq__()并且未定义__hash__()的类将其__hash__()隐式设置为None.

A class that overrides __eq__() and does not define __hash__() will have its __hash__() implicitly set to None.

如果重写__eq__()的类需要保留父类中__hash__()的实现,则必须通过设置__hash__ = <ParentClass>.__hash__

If a class that overrides __eq__() needs to retain the implementation of __hash__() from a parent class, the interpreter must be told this explicitly by setting __hash__ = <ParentClass>.__hash__

从故障单 1549 :

这是有意完成的-如果您定义的比较没有 定义哈希,默认哈希将不匹配您的比较,并且 当用作字典键时,您的对象将无法正常工作.

This was done intentionally -- if you define a comparison without defining a hash, the default hash will not match your comparison, and your objects will misbehave when used as dictionary keys.

(Guido van Rossum)

(Guido van Rossum)

这篇关于继承-__hash__在子类中设置为None的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆