我如何才能使python数据类可哈希化而又不能使它们不变? [英] How can I make a python dataclass hashable without making them immutable?

查看:111
本文介绍了我如何才能使python数据类可哈希化而又不能使它们不变?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说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 to eq=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屋!

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