2013-05-30 6 views
2

Итак, мне нужно пройти через список объектов, используя некоторые из их значений для вычисления, а затем назначить им новые значения.Использование декораторов против итерации для установки значений?

Поскольку многим элементам в списке присваивается одно и то же новое значение, я использовал словарь для хранения списка элементов, для которых требуется такое же значение. Например:

item_dict = {} 

for item in list: 
    value = item.value 
    if value not in item_dict: 
     item_dict[value] = [item] 
    else: 
     item_dict[value].append(item) 

# do some calculations base on values 

new_data # some dictionary created by computation 
# new data is stored new_data[value] = new_value 

for value, new_value in new_data.items(): 
    items = item_dict[value] 
    for item in items: 
     item.value = new_value 

я думаю об удалении для элемента в цикле пунктов с декоратор, так как все new_value (ов) для этого списка являются одинаковыми. Например:

def dec(item): 
    def wrap(value): 
     item.value = value 
    return wrap 

def rec(item, func): 
    def wrap(value): 
     item.value = value 
     func(value) 
    return wrap 

item_dict = {} 

for item in list: 
    value = item.value 
    if value not in item_dict: 
     item_dict[value] = dec(item) 
    else: 
     item_dict[value] = rec(item, item_dict[value]) 

# do some calculations base on values 

new_data # some dictionary created by computation 
# new data is stored new_data[value] = new_value 

for value, new_value in new_data.items(): 
    items = item_dict[value] 
    items(new_value) 

Будет ли мода декоратора быть более эффективной и насколько она будет иметь влияние на память? Есть ли лучшие способы сделать это?

+0

Функция 'rec', с первого взгляда, выглядит как нет op. В чем его цель? – Eric

+0

кричит, позвольте мне исправить это – Derek

+1

Вам нужны 'items_dict', чтобы сделать свой расчет? Если вам просто нужно обновить все значения элементов на основе 'new_data', я думаю, что было бы проще просто перебирать ваш список один раз, каждый раз поднимая новое значение. Словарь поиска быстро. –

ответ

1

defaultdict хорошо работает здесь:

from collections import defaultdict 

item_dict = defaultdict(list) 

for item in value_list: 
    item_dict[item.value].append(item) 

# do some calculations base on values 

new_data # some dictionary created by computation 
# new data is stored new_data[value] = new_value 

for value, new_value in new_data.items(): 
    for item in item_dict[value]: 
     item.value = new_value 

Я борюсь, чтобы придумать, как вариант декоратор может быть лучше - с одной стороны, вам не придется беспокоиться о пределе рекурсии.

+0

не могли бы вы объяснить, почему это лучше, чем метод декоратора, т. Е. Насколько повышается производительность и почему? спасибо – Derek

+0

@Derek: метод декоратора, очевидно, требует больше памяти, поскольку вы создаете новый объект функции с закрытием каждого цикла. Мой ответ действительно не отличается от производительности вашего итерационного решения - это просто более сжатый способ выразить это. – Eric

0

Метод get хорошо работает в первом случае.

item_dict = {} 

for item in list: 
    item_dict[item.value] = item_dict.get(item.value, []) + [item] 

Ключом к выполнению этой работы является использование добавления списка вместо добавления, поскольку append возвращает None.

+1

Если вы пойдете так, 'set_default', вероятно, лучше. 'item_dict.set_default (item.value, []). append (item)' –

+0

Не могли бы вы уточнить? Является ли ваш метод более эффективным? Разве вы не устанавливали значение по умолчанию каждый раз, когда мы увидели item.value? – yardsale8

+0

Вы правы, для получения дополнительной информации см. [Этот вопрос] (http://stackoverflow.com/questions/7423428/python-dict-get-vs-setdefault) – yardsale8

Смежные вопросы