我如何才能使python数据类可哈希化而又不能使它们不变? [英] How can I make a python dataclass hashable without making them immutable?
问题描述
说a我在python3中有一个数据类.我希望能够对这些对象进行哈希处理和排序.我不希望这些是一成不变的.
Say a I have a dataclass in python3. I want to be able to hash and order these objects. I do not want these to be immutable.
我只希望它们按ID排序/散列.
I only want them ordered/hashed on id.
我在文档中看到我可以只实现_ hash _以及所有其他功能,但是我想让datacalses为我完成这项工作,因为它们旨在解决这个问题.
I see in the docs that I can just implement _hash_ and all that but I'd like to get datacalsses to do the work for me because they are intended to handle this.
from dataclasses import dataclass, field
@dataclass(eq=True, order=True)
class Category:
id: str = field(compare=True)
name: str = field(default="set this in post_init", compare=False)
a = sorted(list(set([ Category(id='x'), Category(id='y')])))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'Category'
推荐答案
来自文档:
以下是控制
__ hash __()
方法的隐式创建的规则:
Here are the rules governing implicit creation of a
__hash__()
method:
[...]
如果 eq
和 frozen
均为true,则默认情况下 dataclass()
将为您生成一个 __ hash __()
方法.如果 eq
为true,并且冻结
为假, __ hash __()
将设置为 None
,将其标记为不可哈希(它是可变的,因为它是可变的).如果 eq
为false,则 __ hash __()
将会保持不变,这意味着该方法的 __ hash __()
方法将使用超类(如果超类是对象,则意味着它将回退到基于ID的哈希).
If eq
and frozen
are both true, by default dataclass()
will
generate a __hash__()
method for you. If eq
is true and frozen
is false, __hash__()
will be set to None
, marking it unhashable
(which it is, since it is mutable). If eq
is false, __hash__()
will be left untouched meaning the __hash__()
method of the
superclass will be used (if the superclass is object, this means it
will fall back to id-based hashing).
由于您设置了 eq = True
并将默认情况下的 Frozen
保留为( False
),因此您的数据类不可散列.
Since you set eq=True
and left frozen
at the default (False
), your dataclass is unhashable.
您有3个选择:
- 设置
frozen = True
(除了eq = True
之外),这将使您的类不可变且可哈希化. -
设置
unsafe_hash = True
,这将创建__ hash __
方法,但使您的类可变,因此如果在存储时修改了您的类的实例,则可能会出现问题在一个字典或集合中:
- Set
frozen=True
(in addition toeq=True
), which will make your class immutable and hashable. Set
unsafe_hash=True
, which will create a__hash__
method but leave your class mutable, thus risking problems if an instance of your class is modified while stored in a dict or set:
cat = Category('foo', 'bar')
categories = {cat}
cat.id = 'baz'
print(cat in categories) # False
__ hash __
方法.这篇关于我如何才能使python数据类可哈希化而又不能使它们不变?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!