Использование __repr__ с модулем shelve в Python
Я пишу класс-обертку для модуля shelve и собираюсь использовать его как словарь. Вот код:
import shelve
class MyShelve:
def __init__(self, filename='myshelve.db'):
self.s = shelve.open(filename)
def __del__(self):
self.s.close()
def __repr__(self):
return repr(self.s)
def __getitem__(self, k):
return self.s.get(k, None)
def __setitem__(self, k, v):
self.s[k] = v
Казалось, все работало нормально, пока я не использовал выражение "ключ в словах". Это пример сеанса:
>>> d = {'1': 'One', '2': 'Two'}
>>> d
{'1': 'One', '2': 'Two'}
>>> '1' in d
True
>>> from myshelve import MyShelve
>>> s = MyShelve()
>>> s['1'] = 'One'
>>> s['2'] = 'Two'
>>> s
{'1': 'One', '2': 'Two'}
>>> '1' in s.s
True
>>> '1' in s
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "myshelve.py", line 15, in __getitem__
return self.s.get(k, None)
File "/usr/lib64/python2.7/shelve.py", line 113, in get
if key in self.dict:
File "/usr/lib64/python2.7/_abcoll.py", line 369, in __contains__
self[key]
File "/usr/lib64/python2.7/bsddb/__init__.py", line 270, in __getitem__
return _DeadlockWrap(lambda: self.db[key]) # self.db[key]
File "/usr/lib64/python2.7/bsddb/dbutils.py", line 68, in DeadlockWrap
return function(*_args, **_kwargs)
File "/usr/lib64/python2.7/bsddb/__init__.py", line 270, in <lambda>
return _DeadlockWrap(lambda: self.db[key]) # self.db[key]
TypeError: Integer keys only allowed for Recno and Queue DB's
Что я делаю неправильно?
2 ответа
Прежде всего, всегда наследуй от object
, Это избавит вас от многих неприятностей позже. Во-вторых, вам нужно использовать __contains__
, В-третьих, при использовании __contains__
или же __getitem__
или любой другой метод в этом отношении, обязательно используйте исключения, то есть блоки try-кроме. Вот пример того, что вы ищете:
class MyShelve(object):
def __init__(self, filename='myshelve.db'):
self.s = shelve.open(filename)
def __del__(self):
self.s.close()
def __repr__(self):
return repr(self.s)
def __getitem__(self, item):
return self.s.get(item, False)
def __contains__(self, item):
try:
return item in self.s
except TypeError:
return False
def __setitem__(self, k, v):
self.s[k] = v
Демо-версия:
In[3]: from shelving import MyShelve
In[4]: s = MyShelve()
In[5]: s['1'] = 'One'
In[6]: s['2'] = 'Two'
In[7]: '1' in s
Out[7]: True
Обратите внимание, что без исключения блокировать выражение 3 in s
оценил бы это:
Traceback (most recent call last):
(...)
TypeError: gdbm key must be string, not int
Оглядываясь назад, лучше использовать функцию с предварительно сконфигурированными значениями, чем использовать класс в этом случае, потому что вы будете много перезаписывать, и это будет тратить ваше время. Кроме того, проще использовать менеджер контекста, который с функцией, которая возвращает объект файла, а не с классом, который инкапсулирует ваш объект файла (потому что когда вы открываете полку, вы фактически создаете файл).
Попробуй использовать __contain__
метод и настроить случаи. это то, что называет оператор in.
class MyShelve:
def __init__(self,filename='myshelve.db'):
self.s = shelve.open(filename)
def __del__(self):
self.s.close()
def __repr__(self):
return repr(self.s)
def __getitem__(self, k):
return self.s.get(k, None)
def __setitem__(self, k, v):
self.s[k] = v
def __contains__(self, m):
return True if (m in self.s.values() or self.s.keys) else False
def close(self):
self.s.close()
def clear(self):
self.s.clear()
def items(self):
return self._shelve.iteritems()
s= MyShelve()
s['1'] = 'One'
s['2'] = 'two'
print '1' in s #Output: True