Dict-подобный объект без __getitem__, __setitem__
Если вы делаете
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__
если бы вы хотели обернуть их в отсрочку? Единственное решение, которое я вижу, - это обернуть db в служебный класс:
class Db:
def __init__(self, db):
self.db = db
def __getitem__(self, x):
return self.db[x]
...
Но, может быть, я упускаю что-то очевидное?
1 ответ
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'
Как getitem
а также partial
реализованы в C, эта комбо всегда будет быстрее, чем пользовательские объекты, функции или лямбды, чтобы обернуть доступ.