【问题标题】:How to combine dataclass, property, and lru_cache如何组合数据类、属性和 lru_cache
【发布时间】:2019-12-12 18:37:06
【问题描述】:

我正在尝试为一些计算科学代码组合数据类、属性和 lru_caches:

from dataclasses import dataclass
from typing import Any
from functools import lru_cache
@dataclass
class F:
    a: Any = 1
    b: Any = 2
    c: Any = 3
    @property
    @lru_cache(1)
    def d(self):
        print('Computing d')
        return (self.a+self.b)**self.c
f=F()
print(f.d)
print(f.d)

我希望看到

Computing d
27
27

但得到

TypeError: unhashable type: 'F'

有没有办法解决这个问题?

【问题讨论】:

标签: python properties lru python-dataclasses


【解决方案1】:

lru_cache 类似于 memoization,因此它对传递给函数的参数进行哈希处理并存储结果。您的课程不可散列。要使其可散列,请添加类似这样的内容

class F:
    ....
    def __hash__(self):
        return hash((self.a, self.b, self.c))

这样做的原因是这 3 个属性使每个实例“唯一”——我们不需要对方法进行哈希处理,因为所有实例都有相同的方法。

在大多数普通类中,__dict__ 用于一般散列,除非找到 __hash__ 方法。数据类文档解释说数据类可以生成散列方法,但这取决于您如何设置数据类,因为默认情况下对象被假定为可变的(并且像列表这样的可变对象不能被散列)。

数据类文档指出,如果在使用@dataclass() 装饰时将参数eqfrozen 设置为True,则会生成一个哈希方法,但您的应用程序可能不保证这一点,因为frozen 禁止属性实例上的分配。

https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass

【讨论】:

  • 我自己从未使用过数据类,但在 StackOverflow 上搜索后,我得到了这个:docs.python.org/3/library/…
  • 感谢您的更新。这让我意识到我不能在我的真实课堂上让我的生活变得轻松,而只是让def __hash__(self): return 0。由于python的''light-OO''方法,所有实例的lru_cached方法实际上是相同的方法,使用不同的self参数调用,所以如果我有两个F实例并使用我的假哈希,他们'会给self.d同样的答案
  • 完全正确。实例“拥有”的方法实际上是类本身中保存的同一个对象,因此每个实例都必须有一个新的哈希来区分它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-26
  • 2013-01-03
  • 1970-01-01
  • 2019-01-03
  • 1970-01-01
  • 2018-07-14
  • 2015-09-23
相关资源
最近更新 更多