1

如果你这样做

import gdbm
db = gdbm.open('foo', 'cs')

你得到一个对象,它是:

<gdbm.gdbm at 0x7f0982b9aef0>

您现在可以通过以下方式在数据库中设置键和值:

db['foo'] = 'bar'
print db['foo']

我想使用 Twisted 中的这些并为它制作一个包装器__getitem____setitem__返回延迟。但是,我注意到了一些奇怪的事情:

In [42]: dir(db)
Out[42]: ['close', 'firstkey', 'has_key', 'keys', 'nextkey', 'reorganize', 'sync']

这个对象没有__getitem____setitem__。尝试其中任何一个都会导致属性访问错误。然而,它的行为就像一本字典。这是一个什么样的物体?

(我怀疑这是一个 C 扩展对象,但我觉得奇怪的是它具有类似 dict 的访问方法,但没有__getitem____setitem__方法。指向描述此行为的 Python 文档的指针会很有帮助。)

进一步:你将如何获得引用db.__getitem__db.__setitem__如果你想将它们包装在一个 deferred 中?我看到的唯一解决方案是将 db 包装在实用程序类中:

class Db:
    def __init__(self, db):
         self.db = db

    def __getitem__(self, x):
         return self.db[x]

    ...

但也许我错过了一些明显的东西?

4

1 回答 1

3

gdbm确实是一个 C 模块;该对象改为实现 C-API映射协议。

请参阅带有函数指针的结构的源代码。PyMappingMethods

您可以operator.getitem()用来访问密钥:

>>> from operator import getitem
>>> db['foo'] = 'bar'
>>> getitem(db, 'foo')
'bar'

您可以使用一个参数将其包装getitem()functools.partial()有效的可调用对象:

>>> from functools import partial
>>> gi = partial(getitem, db)
>>> gi('foo')
'bar'

正如在 Cgetitempartial实现的那样,这个组合总是比自定义对象、函数或 lambda 更快地包装访问。

于 2013-10-06T23:40:00.447 回答