如何在数据库中保存昂贵答案的适当pythonic池/缓存对象中有效?
我的模块包含以下示意图代码:
import sqlite3
db = sqlite3.connect(config.DB) # application shared database
db.row_factory = sqlite3.Row
class Foo:
def __init__(self, id):
self.id = id
@property
def bar(self):
if not hasattr(self, '_bar'):
row = db.execute(
'SELECT bar FROM bars WHERE id=?', (self.id, )).fetchone()
self._bar = row['bar'] if row else None
return self._bar
应用程序正在创建其生命周期Foo
个对象,以访问数据库中的某些值bar
。 Foo.bar
属性表示昂贵的操作,因此是惰性处理。 Foo
类的实例根本没有太大变化,它们只是数据库存储数据的读代理。
现在我意识到,具有相同Foo
的{{1}}个实例经常被创建和销毁。每次对象死亡时,id
的知识都会丢失,必须在以后再次从数据库中获取。
我想出了两种方法来处理它,或者自己汇集对象:
Foo.bar
或他们的州:
class DBObject:
_pool = {}
def __new__(cls, *params, **key_params):
key = cls.__name__ + str(params) + str(key_params)
if not key in DBObject._pool:
self = object.__new__(cls, *params, **key_params)
DBObject._pool[key] = self
self = DBObject._pool[key]
return self
class Foo(DBObject):
...
是否有一些更好,更pythonic的解决方案?我监督了什么吗?
PS:我是Python初学者,具有Java / C ++背景。
答案 0 :(得分:1)
我会使用一个简单的memoize装饰器,这是一个通用的:
import functools
def memoize(func):
cache = {}
sentinel = object()
@functools.wraps(func)
def wrapper(*args, **kwargs):
key = (args, tuple(kwargs.items()))
result = cache.get(key, sentinel)
if result is not sentinel:
return result
result = func(*args, **kwargs)
cache[key] = result
return result
return wrapper
您可以使用它来装饰Foo
类:
@memoize
class Foo:
...
您还可以将memoize
装饰器应用于bar
方法,并稍微清理一下:
@property
@memoize
def bar(self):
row = db.execute('SELECT bar FROM bars where id=?', (self.id, )).fetchone()
return row['bar'] if row else None
Python3.2中的新功能还有functools.lru_cache
,它具有许多不错的功能(清除缓存,跟踪命中/未命中统计信息,可选大小和类型检查)
答案 1 :(得分:0)