首页 > 解决方案 > 提供仅在首次使用时才计算的类对象属性的正确方法,然后在再次引用时保存?

问题描述

我创建了一个类(本质上是整数的子类元组),我将一次创建它的许多实例以形成一个用于分析的大型数据集。

我希望能够查询有关实例的某些内容,例如它们的总和、平均值、标准差、范围、最大值和最小值等。有时我只会访问这些属性之一,因此希望避免全部计算它们作为 __init__ 中的属性。但是,有时我可能会多次访问它们,并且数据本身不会改变,所以我想避免重复调用每次重新计算值的方法,而是在最初计算后将其保存为属性.

但理想情况下,我不想区分这个值的初始调用和我这样做的未来时间。

我认为@properties 可能是这样做的方法,但在进一步阅读时,它们似乎不太合适,因为我认为它们仍然会在 __init__ 中计算,而且我不需要通过调用以外的任何东西来设置它们对自己。四处搜索我没有找到太多其他东西,但很难知道我是否使用了正确的关键字,好像有一个内置功能我不知道它叫什么。

这是我到目前为止所得到的(简化的),它确实表现出我想要的样子。

from random import randint

class ListOfRandoms(tuple):
    def __new__(cls, upper_limit, count):
        data = tuple(sorted((randint(1, upper_limit) for _ in range(count)), reverse=True))
        return super().__new__(ListOfRandoms, data)

    def __init__(self, upper_limit, count):
        self._avg = None
        self._high = None
        self._low = None
        self._range = None

    def __str__(self):
        return ", ".join([str(value) for value in self])

    def avg(self):
        if not self._avg:
            self._avg = sum(self) / len(self)
        return self._avg

    def high(self):
        if not self._high:
            self._high = self[0]
        return self._high

    def low(self):
        if not self._low:
            self._low = self[len(self)-1]
        return self._low

    def range(self):
        if not self._range:
            self._range = self.high() - self.low()
        return self._range

并进行一些测试以证明它的行为正确(通常我只会通过调用方法而不是私有属性本身来获取值)。

test_list = ListOfRandoms(20, 6)

print(test_list)
print(test_list._range)    # starts unset
print(test_list.range())   # calculated
print(test_list._range)    # is now set
print(test_list._high)     # was set as part of range calc
print(test_list._avg)      # has not been calculated
test_list._range = 99999   # to prove it is not recalculated when called again
print(test_list.range())   # it is not

输出:

17, 13, 10, 4, 3, 1
None
16
16
17
None
99999

所以我真正想知道的是,是否有一个特定的内置 Python 功能我应该用来完成这类事情?否则,如果我应该采取完全不同的方法,那么朝着正确的方向推进也会很棒。谢谢。

标签: pythonclassattributes

解决方案


推荐阅读