在Python3中冻结集子类的实例是否应该是散列的?

2024-10-02 20:44:03 发布

您现在位置:Python中文网/ 问答频道 /正文

根据https://docs.python.org/2/library/stdtypes.html#frozenset,在python2中:

The frozenset type is immutable and hashable -- its contents cannot be altered after is created; however, it can be used as a dictionary key or as an element of another set.

但是根据https://docs.python.org/3.4/library/stdtypes.html#frozenset,在python3中,我看不到任何信息表明冻结集实例(或子类)应该是散列的,只有set/frozenset元素:

Set elements, like dictionary keys, must be hashable.

那么,下面的代码应该适用于任何python3解释器,还是最后一行应该引发一个TypeError

# Code under test
class NewFrozenSet(frozenset):
    def __eq__(self, other):
        return True

    # Workaround: Uncomment this override
    # def __hash__(self):
    #     return hash(frozenset(self))

hash(frozenset())
hash(NewFrozenSet())

10.10 pyosemite系统

^{pr2}$

OSX Yosemite 10.10,使用自制程序http://brew.sh/

$ brew install python3
$ python3
Python 3.4.2 (default, Jan  5 2015, 11:57:21)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.56)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> class NewFrozenSet(frozenset):
...     def __eq__(self, other):
...         return True
...
>>> hash(frozenset())
133156838395276
>>> hash(NewFrozenSet())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'NewFrozenSet'
>>>

Ubuntu 14.04.1 LTS(x86_64),系统python3

$ python3
Python 3.4.0 (default, Apr 11 2014, 13:05:11)
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class NewFrozenSet(frozenset):
...     def __eq__(self, other):
...         return True
...
>>> hash(frozenset())
133156838395276
>>> hash(NewFrozenSet())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'NewFrozenSet'
>>>

这是Python3中的回归,还是经过深思熟虑的设计选择?


Tags: orselftruereturndeftypehashbe
1条回答
网友
1楼 · 发布于 2024-10-02 20:44:03

根据hashable的定义:

Hashable objects which compare equal must have the same hash value.

现在您已经实现了一个新的__eq__方法,但没有实现NewFrozenSet的新__hash__。Python现在不能假设上面的属性成立(即__eq__和{}的行为匹配),所以它不能假设类型是散列的。这就是为什么您需要同时实现__eq__和{}以使类型散列(或者不实现其中任何一个并使用父类中的方法)。在

例如,如果省略__eq__,那么NewFrozenSet将变为散列:

class NewFrozenSet(frozenset):
    pass

如果这在NewFrozenSet中不正确,那么您需要同时实现__eq__和{}。在

相关问题 更多 >