【问题标题】:Using __repr__ with shelve module in Python在 Python 中将 __repr__ 与搁置模块一起使用
【发布时间】:2014-12-20 22:32:06
【问题描述】:

我正在为 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

在我使用“key in dict”之前,一切似乎都很好。这是一个示例会话:

>>> 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

我做错了什么?

【问题讨论】:

  • 您需要使用s.keys()
  • 我试过了,它给了我这个错误:&gt;&gt;&gt; s.keys() Traceback (most recent call last): File "&lt;stdin&gt;", line 1, in &lt;module&gt; AttributeError: MyShelve instance has no attribute 'keys'我喜欢“字典中的键”表达式,我想在持久字典中实现它。
  • 我会在 15 分钟内给你答复。问题是你只是做错了__getitem____setitem__。查看文档。

标签: python persistence shelve repr


【解决方案1】:

首先,始终从object 继承。以后可以省去很多麻烦。其次,您需要使用__contains__。第三,当使用 __contains____getitem__any dunder 方法时,请确保使用异常,即 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

事后看来,在这种情况下,使用具有预配置值的函数比使用类更好,因为您将覆盖很多东西,这会浪费您的时间。此外,使用带有返回文件对象的函数的上下文管理器比使用封装文件对象的类更容易(因为当您打开搁架时,实际上是创建了一个文件)。

【讨论】:

  • 谢谢!我没有考虑除块之外的尝试的重要性。
  • @czayas 我的建议是完全不要让课程覆盖你的书架。你不会得到所有的好东西,比如上下文管理器和shelve.open() 提供的其他东西。另外,如果这个答案对你有帮助,别忘了点赞:)
【解决方案2】:

尝试使用__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

【讨论】:

  • 他想要一个书架,而不是字典。
  • @Games Brainiac:是的,结果相同。
  • 同意,但是如果你正在创建一个类来封装一个字典,并用默认方法的镜像副本覆盖它的默认方法,那么你做的并不多。
  • 这对我有用:def __contains__(self, k): return True if k in self.s else False 这似乎与字典的行为一致。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-19
相关资源
最近更新 更多