2014-10-09 5 views
-1

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

Вкратце я хочу хранить ценности как это; synset_cache[word1][word1_tag][word2][word2_tag] = score

class MyClass(Object): 

    def __init__(self): 
     MyClass.synset_cache={} #dict 

    def set_cache(self,word1, word1_tag, word2, word2_tag, score) 
     try: 
      MyClass.synset_cache[word1] 
     except: 
      MyClass.synset_cache[word1]={} #create new dict 
     try: 
      MyClass.synset_cache[word1][word1_tag] 
     except: 
      MyClass.synset_cache[word1][word1_tag]={} #create new dict 
     try: 
      MyClass.synset_cache[word1][word1_tag][word2] 
     except: 
      MyClass.synset_cache[word1][word1_tag][word2]={} #create new dict 
     #store the value 
     MyClass.synset_cache[word1][word1_tag][word2][word2_tag] = score 

Но я получаю эту ошибку.

Type error: list indices must be integers, not unicode 

номер строки это свидетельствует в MyClass.synset_cache[word1][word1_tag]={} #create new dict.

Как я могу заставить это работать?

EDIT: Согласно комментариям @ Rob comments о его ответе; Я назначил список этому MyClass.synset_cache другим способом (обратите внимание, что он находится на уровне класса). Таким образом, эта часть кода не имела ошибок.

+0

Кто когда-либо проголосовал? могу я узнать почему? –

ответ

1

Использование dict.setdefault.

Это может работать:

#UNTESTED 
d = MyClass.synset_cache.setdefault(word1, {}) 
d = d.setdefault(word1_tag, {}) 
d = d.setdefault(word2, {}) 
d[word2_tag] = score 

В качестве альтернативы, вы можете использовать этот удобный рекурсивный defaultdict, вырастающий новые уровни Словаря автоматически. (См.: here и here)

import collections 
def tree(): 
    return collections.defaultdict(tree) 

class MyClass(Object): 
    def __init__(self): 
     MyClass.synset_cache=tree() 

    def set_cache(self,word1, word1_tag, word2, word2_tag, score) 
     MyClass.synset_cache[word1][word1_tag][word2][word2_tag] = score 
+0

Хорошо, я попробую :) –

+0

получение атрибута AttributeError: list не имеет атрибута 'setdefault' в' d = d.setdefault (word1_tag, {}) '. –

+1

Тогда у вас есть код вне того, что вы показали нам, что делает что-то вроде MyClass.synset_cache [word1] = [] '. Пожалуйста, уменьшите свою программу до наименьшей возможной программы, которая демонстрирует проблему, и скопируйте всю вашу короткую программу в исходный вопрос. –

0

Это будет зависит от данных, по меньшей мере, для некоторых тестовых данных (смотри ниже), код не производит эту ошибку. Как вы это называете?

Также обратите внимание, что как написано выше, он не будет скомпилирован из-за некоторых синтаксических ошибок (т. Е. Ни один двоеточие не завершит линию def set_cache).

Ниже приведены некоторые переделаны к компиляции кода с некоторым вызовом, например данные, и как это довольно отпечатки:

#!/usr/bin/env python 

import pprint 

class MyClass(): 

    def __init__(self): 
     MyClass.synset_cache={} #dict 

    def set_cache(self,word1, word1_tag, word2, word2_tag, score): 
     try: 
      MyClass.synset_cache[word1] 
     except: 
      MyClass.synset_cache[word1]={} #create new dict 
     try: 
      MyClass.synset_cache[word1][word1_tag] 
     except: 
      MyClass.synset_cache[word1][word1_tag]={} #create new dict 
     try: 
      MyClass.synset_cache[word1][word1_tag][word2] 
     except: 
      MyClass.synset_cache[word1][word1_tag][word2]={} #create new dict 
     #store the value 
     MyClass.synset_cache[word1][word1_tag][word2][word2_tag] = score 


x = MyClass() 

x.set_cache('foo', 'foo-tag', 'bar', 'bar-tag', 100) 

pp = pprint.PrettyPrinter(indent=4) 

pp.pprint(x.synset_cache) 

Какие выходы:

пара другие вещи примечание .. .

Я бы порекомендовал использовать синтаксис in для проверки присутствия клавиш, а не try - except. Он более компактный и более Pythonic.

Кроме того, ваша основная переменная, synset_cache, является классом (то есть статическим). Вы имели в виду, что это так?

+0

Извините, код, который я вставил здесь, не ошибся. Как заметил @Rob, я присваивал список на этом же var другим методом ошибочным. –

+0

Я использую несколько потоков, и расчетное сходство дорого. поэтому я решил кэшировать его на уровне класса и использовать 'threading.Lock()'. –

+1

Ах. Я по-прежнему рекомендую переключиться на синтаксис проверки ключа 'in', хотя (не то, что он имеет функциональную разницу, только по причинам, упомянутым выше). – khampson

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