2015-07-22 3 views
0

Я ищу хранилище объектов в python, что позволяет мне хранить словарь, имеющий tuple s как ключи. Я уже пробовал shelve и shove, которые оба выходят с ошибкой, как только я передаю свой словарь. Существуют ли какие-либо решения, обеспечивающие это?хранение объектов в python, которые позволяют кортежи как ключи

Для пуш,

from shove import Shove 
data = Shove('file://tmp') 
("a",) in data 

это дает мне AttributeError: 'tuple' object has no attribute 'rstrip'. Но только, если кортеж не находится в данных.

from shove import Shove 
data = Shove('file://tmp') 
data[("a",)] = 2 
("a",) in data 

не будет выдавать ошибку.

Для полки,

import shelve 
d = shelve.open('tmp/test.db') 
d[('a',)] = 2 

дает мне TypeError: dbm mappings have string indices only

+0

Вы пробовали рассол? –

+0

... какой * "ошибка" *? – jonrsharpe

+0

@PadraicCunningham Я хотел бы иметь простоту доступа к данным только с помощью 'data [tuple (key1, key2)] = 3', так как он предоставляется с помощью полки и форсунки. Я подумал с рассолом, я могу загрузить или сохранить весь словарь –

ответ

0

shelve представляет собой модуль из стандартной библиотеки Python. Док ясно о том, что: значения (! А не ключи) в полке может быть по существу произвольные объекты Python - все, что модуль рассол может обрабатывать ... Ключи обычные строки

По строительной полке будет только принимать строки как ключи.

Shove по-прежнему находится в Бета-версии в соответствии с документацией от pypi, и я не видел никаких доказательств того, что он поддерживает что-либо другое, что строка для ключа (ошибка object has no attribute 'rstrip' не думает, что это не так).

Если бы я был вами, я бы придерживался хорошо известного shelve и просто обернул его ключевым слоем сериализации. Как предложил Падрейк Каннингем, pickle должен выполнить эту работу.

Вот (не тщательно протестированы) возможная реализация:

class tuple_dict(collections.MutableMapping): 
    class iterator(collections.Iterator): 
     def __init__(self, d): 
      self.it = d.udict.__iter__() 
     def __iter__(self): 
      return self 
     def next(self): 
      return pickle.loads(next(self.it)) 
    def __init__(self, udict): 
     self.udict = udict 
    def __getitem__(self, key): 
     ukey = pickle.dumps(key) 
     return self.udict[ukey] 
    def __setitem__(self, key, value): 
     ukey = pickle.dumps(key) 
     self.udict[ukey] = value 
    def __delitem__(self, key): 
     ukey = pickle.dumps(key) 
     del self.udict[ukey] 
    def keys(self): 
     return [ pickle.loads(key) for key in self.udict.keys() ] 
    def __iter__(self): 
     return self.iterator(self) 
    def __len__(self): 
     return len(self.udict) 
    def __contains__(self, key): 
     return pickle.dumps(key) in self.udict 
    def sync(self): 
     self.udict.sync() 
    def close(self): 
     self.udict.close() 

Вы могли бы использовать его таким образом:

import shelve 
underlying_d = shelve.open('tmp/test.db') 
d = tuple_dict(underlying_d) 

d будет принимать кортеж в качестве ключей и магазинов, которые все в нижележащих полка.

NB: если позже вы захотите использовать другую реализацию сохранения, если реализация является сопоставлением (тип типа dict), вы можете повторно использовать tuple_dict, просто изменив методы закрытия и синхронизации (спецификация полки), но что будет требуемый другим имплантантом. Фактически, помимо этих двух методов tuple_dict просто обертывает обычный dict - и как таковой любой класс отображения ...

0

Не знаю, как это pythonic это ...как об определении постоянной строки разделителя как нечто почти невозможное, чтобы произойти в ваших ключевых строках:

sep = '#!#!#!#' 

, а затем, когда вам нужно создать ключ для shelve из кортежа строк, просто .join их в сырую нефть хэш:

import shelve 
d = shelve.open('tmp/test.db') 
d[sep.join(('a',))] = 2 

Если вам необходимо необходимо регенерировать tuple ключ из информации, содержащейся в shelve хранилище, это так просто, как .split:

my_dict = { tuple(k.split(sep)): d[k] for k in d.keys() } 

Per here, этот прямой dict синтаксис понимания поддерживается только для Python 2.7 и новее, но есть альтернативы для 2.6 и более ранних версий.

В вашем случае, так как у вас уже есть словарь определено, вы должны сделать некоторые Dict-фу в горячие замены текущих tuple ключей для str -ified хэша при взаимодействии с shelve хранилища, но это не должно быть слишком тяжелым.

Этот подход не является полностью ошибка свободной, но, вероятно, могут быть сделаны таким образом, что вероятность проблем, возникающих при столкновениях sep с tuplestr -of- ключей исчезающе мала. Также обратите внимание, что этот подход будет работать, только если ваши ключи строгоtuple s str s.