Оптимизация значений суммирования словарного цикла - PullRequest
0 голосов
/ 31 декабря 2018

У меня есть метод, который принимает вложенный dict input_dict

final = 0
for key, value in input_dict[self.state][self.city].iteritems():
    age = self._get_age(key)
    if (age > 0 and age < MAX_VAL):
      final += value  * self.lookup[key][age] * self.multiplier

return final

Это выполняется примерно за 0,03 секунды, но, учитывая, что в примере выполнения он вызывается> 10k раз, он оказываетсяузкое место и отвечает за около 50% времени выполнения.Предполагая, что я не могу уменьшить общее количество раз, когда метод вызывается, есть ли у кого-нибудь предложения, как это улучшить?

Ответы [ 2 ]

0 голосов
/ 01 января 2019

Возможно, рассмотрим что-то вроде следующего:

current_period = self.current_period - (self.current_period % 7)
MIN_VALUE = current_period - 7 * MAX_VALUE
return self.multiplier * sum(value * self.lookup[key][self._get_age(key)]
    for key, value in input_dict[self.state][self.city].iteritems()
    if MIN_VALUE < key < current_period
)

Здесь я извлекаю умножение на self.multiplier из цикла и заменяю сравнение 0 < age < MAX_VALUE эквивалентным сравнением предварительно вычисленных значений, полученныхзамена age на ваш _get_age() метод, описанный в комментариях, и решение для key.Это позволяет нам пропустить вызов функции + дополнительные вычисления для случаев, когда age <= 0 or age >= MAX_VALUE, и не требует дополнительных затрат (за исключением вычисления 2 переменных вне цикла) по сравнению с оригиналом, если 0 < age < MAX_VALUE.Кроме того, это позволяет нам использовать встроенную функцию sum(), которая обычно быстрее, чем суммирование через цикл for, но без создания отдельного генератора, как в ответе qxz.

Обратите внимание, что я предполагаю (self.current_period - period) в вашем _get_age() методе является целое число, поэтому / 7 выводит результат в Python-2.x.Если это не так, удалите - (self.current_period % 7) из назначения current_period для эквивалентной функциональности.

0 голосов
/ 31 декабря 2018

Встроенная функция sum обычно быстрее, чем запись цикла for.(См. этот вопрос .) В вашем случае вы можете сгенерировать выражение генератора значений для суммирования, а затем передать его sum:

items = (
    (key,value,self._get_age(key))
    for key,value in input_dict[self.state][self.city].iteritems()
)
return sum(
    value * self.lookup[key][age] * self.multiplier
    for key,value,age in items
    if 0 < age < MAX_VAL
)
...