2017-01-23 8 views
1

Скажите, что у меня есть поток входящих элементов, которые я обрабатываю. Для каждого элемента я извлекаю некоторые данные и сохраняю их. Но много предметов одинаково. Я хочу отслеживать их получение, но не хранить одни и те же данные более одного раза. Я могу реализовать это так, но это кажется неуклюжим:Нормально ли использовать объект в качестве собственного ключа в словаре/hashmap (в python)?

item_cache = {} 
item_record = [] 

def process(input_item): 
    item = Item(input_item) # implements __hash__ 
    try: 
     item_record.append(item_cache[item]) 
    except KeyError: 
     item_cache[item] = item # this is the part that seems weird 
     item_record.append(item) 

Я просто переусердствовал это? Делает d[thing] = thing довольно нормальную конструкцию в python?

EDIT

В ответ на комментарий ниже. Вот более полный пример, показывающий, как этот код позволяет избежать дублирования копий входных данных.

class Item(object): 
    def __init__(self, a, b, c): 
     self.a = a 
     self.b = b 
     self.c = c 

    def __eq__(self, other): 
     return self.a == other.a and self.b == other.b and self.c == other.c 

    def __ne__(self, other): 
     return not (self == other) 

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

    def __repr__(self): 
     return '(%s, %s, %s)' % (self.a, self.b, self.c) 


item_cache = {} 
item_record = [] 


def process_item(new_item): 
    item = Item(*new_item) 
    try: 
     item_record.append(item_cache[item]) 
    except KeyError: 
     item_cache[item] = item 
     item_record.append(item) 

    del item # this happens anyway, just adding for clarity. 

for item in ((1, 2, 3), (2, 3, 4), (1, 2, 3), (2, 3, 4)): 
    process_item(item) 

print([id(item) for item in item_record]) 
print(item_record) 
+1

Если 'thing' является неизменным (и это должно быть, иначе вы не можете использовать его в качестве ключа), возможно,' set() 'является лучшим контейнером для кеша? – DyZ

+0

Из контекста, будет ли лучше использовать какое-либо свойство объекта как ключевое слово item.some_unique_id (может быть кортеж/составной из других свойств) , который уже хешируется и, надеюсь, неизменен? –

ответ

3

К сожалению, да. На самом деле это немного над мыслями. Все, что вам нужно сделать, это использовать sets

Установленный объект представляет собой неупорядоченный набор различных хешируемых объектов. Общее использование включает тестирование членства, удаление дубликатов из последовательности и вычисление математических операций, таких как пересечение, объединение , разность и симметричная разность.

Ваш код может быть заменен

item_record = set() 
for .... : 
    item_record.add(input_item) 

обновление хотя вы говорите «но не сохранять одни и те же данные несколько раз» ваш код на самом деле делает хранить деталь больше, чем один. В исходном коде, вызов item_record.append() будет выполняться независимо от того, существует ли или нет элемент в кэше пункт

try: 
    item_record.append(item_cache[item]) 
except KeyError: 
    item_cache[item] = item # this is the part that seems weird 
    item_record.append(item) 

Так что список будет иметь дубликаты. Однако я не совсем уверен, добавляете ли вы нужные объекты, потому что вы не поделились кодом для своего класса Item. Я считаю, что у нас действительно есть xy problem. Почему бы не задать новый вопрос и объяснить, что вы пытаетесь решить.

+0

, если у меня есть несколько item_records? день новый каждый раз, когда я получаю новый большой кусок входных данных. Я все еще хочу один кеш, но я не могу использовать ту же структуру для записи. – Ferguzz

+0

Я не понимаю вашего комментария – e4c5

+0

um, хорошо, но я думаю, что лучше прояснить комментарий здесь. – e4c5