Python устанавливает больше свойств с 1 вызовом - PullRequest
0 голосов
/ 25 сентября 2018

У меня очень дорогой метод, который возвращает 2 значения, и он вызывается классом A.Поскольку это дорого, я сделал ленивые оценки 2 значений, используя свойства.Поскольку я не хочу вызывать very_expensive_function 2 раза, в первый раз, когда пользователь хочет получить доступ к одному из 2 значений, я сохраняю оба.

Пока что я написал это:

class A:
    def __init__(self):
        self._attr1 = None
        self._attr2 = None

    @property
    def attr1(self):
        self.calculate_metrics()
        return self._attr1


    @property
    def attr2(self):
        self.calculate_metrics()
        return self._attr2

    def calculate_metrics():
        if self._attr1 is None:
            attr1, attr2 = very_expensive_call()
            self._attr1 = attr1
            self._attr2 = attr2

Как видите, при первом обращении пользователя к attr1 или attr2 я сохраняю оба.Это правильно или это возможно по-другому?Кажется очень странным, что каждый раз копируют calculate_metrics().

1 Ответ

0 голосов
/ 25 сентября 2018

Запоминание, проще говоря, запоминание, если вы уже вызывали функцию с конкретными аргументами.Если он у вас есть, он просто возвращает уже рассчитанное возвращаемое значение, а не вычисляет его снова.

import time
def long_calculation(x, y, memo={}):
    try:
        result = memo[x, y] # already calculated!
    except KeyError:
        # make long_calculation take a long time!
        time.sleep(2)
        result = x * y
        memo[x, y] = result
    return result

Словарь memo может запоминать вызовы функции, поскольку он вычисляется при первой загрузке функции:при каждом вызове long_calculation используется один и тот же словарь memo.

Чтобы проверить это, попробуйте:

# Note that (2,2) (7,8) and (10,10) are repeated here:
test_values = ((2,2),(4,5),(2,2),(7,8),(2,3),(7,8),(10,11),(4,5),(10,10),(10,10))

for values in test_values:
    start = time.time()
    res = long_calculation(*values)
    end = time.time()
    elapsed = end-start
    print(values,' calculated in ',elapsed, "seconds")

Вставить такой код в ваш класс должно быть довольно легко.Если вам всегда нужны вычисленные атрибуты, вы можете поместить вызов в __init__.

...