0

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

私は何を間違っていますか?

4

2 に答える 2

1

何よりもまず、常に から継承しobjectます。後で多くのトラブルからあなたを救います。次に、 を使用する必要があります__contains__。第 3 に、__contains__または__getitem__またはその他ダンダー メソッドを使用する場合は、必ず例外を使用してください。つまり、try-except ブロックを意味します。探しているもののサンプルを次に示します。

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

後から考えると、この場合、クラスを使用するよりも、事前に構成された値を持つ関数を使用する方が適切です。多くのものを上書きすることになり、時間を無駄にするからです。さらに、ファイル オブジェクトをカプセル化するクラスを使用するよりも、ファイル オブジェクトを返す関数を使用するコンテキスト マネージャーを使用する方が簡単です (シェルフを開くと、実際にファイルが作成されるため)。

于 2014-10-25T04:09:21.097 に答える
1

メソッドを使用し __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
于 2014-10-25T03:51:02.757 に答える