If you do
import gdbm
db = gdbm.open('foo', 'cs')
You get an object which is:
<gdbm.gdbm at 0x7f0982b9aef0>
You can now set keys and values in the database via:
db['foo'] = 'bar'
print db['foo']
I wanted to use these from Twisted and make a wrapper for __getitem__
and __setitem__
which returns deferreds. However, I noticed something peculiar:
In [42]: dir(db)
Out[42]: ['close', 'firstkey', 'has_key', 'keys', 'nextkey', 'reorganize', 'sync']
This object hasn't got __getitem__
and __setitem__
. Trying either of these gives an attribute access error. Yet, it behaves like a dictionary. What sort of object is this?
(I suspect this is a C extension object, but I find it odd that it has dict-like access methods, but no __getitem__
and __setitem__
methods. A pointer to Python doc describing this behavior would be helpful.)
Further: how would you get references to db.__getitem__
and db.__setitem__
if you wanted to wrap them in a deferred? The only solution I see is to wrap db in a utility class:
class Db:
def __init__(self, db):
self.db = db
def __getitem__(self, x):
return self.db[x]
...
But perhaps I am missing something obvious?
gdbm
is indeed a C module; the object implements the C-API mapping protocol instead.
See the source code for the PyMappingMethods
structure with function pointers.
You could use operator.getitem()
to access the keys:
>>> from operator import getitem
>>> db['foo'] = 'bar'
>>> getitem(db, 'foo')
'bar'
You could wrap getitem()
in functools.partial()
to make it an efficient callable with one argument:
>>> from functools import partial
>>> gi = partial(getitem, db)
>>> gi('foo')
'bar'
As getitem
and partial
are implemented in C, this combo will always be faster than custom objects, functions or lambdas to wrap the access.