Python 动态分配对象/dict方法,该方法在首次访问时用函数结果覆盖自身
我想这将是一个有趣的周日早上的问题。已经三个小时了,我离这里还很远 背景: 我正在使用Python 动态分配对象/dict方法,该方法在首次访问时用函数结果覆盖自身,python,caching,optimization,memoization,Python,Caching,Optimization,Memoization,我想这将是一个有趣的周日早上的问题。已经三个小时了,我离这里还很远 背景: 我正在使用dogpile缓存SqlAlchemy中的只读数据 我将一行数据转换为名为objectifieddit的dict的自定义子类。这让我可以用对象表示法处理dict,这样我就可以像处理活动的SqlAlchemy对象一样,为这些只读dict使用相同的模板和帮助程序。(我也喜欢将缓存数据存储为dict,这样我就可以将相同的缓存值用于其他应用程序或语言) 一切都很顺利 我一直在探索提高缓存性能的方法,还记得Pyramid
dogpile
缓存SqlAlchemy
中的只读数据
我将一行数据转换为名为objectifieddit
的dict的自定义子类。这让我可以用对象表示法处理dict,这样我就可以像处理活动的SqlAlchemy对象一样,为这些只读dict使用相同的模板和帮助程序。(我也喜欢将缓存数据存储为dict,这样我就可以将相同的缓存值用于其他应用程序或语言)
一切都很顺利
我一直在探索提高缓存性能的方法,还记得Pyramid的@reify
decorator()@reify允许对象方法用function的返回值覆盖自身,这样底层函数只调用一次。出于缓存的目的,这个想法对我很有吸引力
[如评论中所述,备忘录是一个更恰当的术语]
问题:
我不知道如何最好地处理这样的事情。尝试动态设置对象属性以重新定义它们自己比我想象的要困难得多@reify
非常简单,而且工作非常好,因为它位于预定义的类上
到目前为止,我想到的最好的是这个
class ReifiedObjectFunction(object):
def __init__(self, object , object_attribute, function , *args , **kwargs ):
self.object = object
self.object_attribute = object_attribute
self.function = function
self.args = args
self.kwargs = kwargs
try:
self.__doc__ = function.__doc__
except: # pragma: no cover
pass
def __repr__(self):
val = self.function(*self.args,**self.kwargs)
setattr( self.object , self.object_attribute , val )
return val
class ObjectifiedDict(dict):
def __getattr__(self,attr):
if attr in self:
return self[attr]
return self.__getattribute__(attr)
def lazyload( self, attr , function , *args , **kwargs ):
self[attr] = ReifiedObjectFunction(self,attr,function,*args,**kwargs)
def lazyloaded_function(*args,**kwargs):
print 'compute lazyloaded_function %s,%s' % ( args , kwargs )
return "%s" % args
sample = ObjectifiedDict({'a':'a','b':'bb','c':'ccc'})
print "get a"
print " %s" % sample.a
print "get b"
print " %s" % sample.b
print "set d"
sample.lazyload( 'd' , lazyloaded_function , "dddd" )
print "d is set"
print "sample : %s" % sample
print "get d"
print " %s" % sample.d
print "get d again"
print " %s" % sample.d
print "sample : %s" % sample
不过,这有几个明显而巨大的警告。它只适用于字符串上下文(因为我正在重载repr),并且只能返回字符串值
有人知道我该怎么做吗
更新:
我想出了这个我想做的工作的例子。是否有人认为这种方法存在任何问题:
class LazyloadedFunction(object):
def __init__(self, object , object_attribute, function , *args , **kwargs ):
self.object = object
self.object_attribute = object_attribute
self.function = function
self.args = args
self.kwargs = kwargs
try:
self.__doc__ = function.__doc__
except: # pragma: no cover
pass
def execute(self):
val = self.function(*self.args,**self.kwargs)
return val
class ObjectifiedDict(dict):
def __getitem__(self,attr):
if attr in self:
item = dict.__getitem__(self,attr)
if isinstance( item , LazyloadedFunction ):
item = item.execute()
dict.__setitem__( self , attr , item )
return item
def __getattr__(self,attr):
if attr in self:
if isinstance( self[attr] , LazyloadedFunction ):
self[attr] = self[attr].execute()
return self[attr]
return self.__getattribute__(attr)
def __getattribute__(self,attr):
return dict.__getattribute__(self,attr)
def lazyload( self, attr , function , *args , **kwargs ):
self[attr] = LazyloadedFunction(self,attr,function,*args,**kwargs)
def lazyloaded_function(*args,**kwargs):
print 'compute lazyloaded_function %s,%s' % ( args , kwargs )
return [1,2,3]
sample_a = ObjectifiedDict({'a':'a','b':'bb','c':'ccc'})
sample_a.lazyload( 'd' , lazyloaded_function , "dddd" )
sample_b = ObjectifiedDict({'a':'a','b':'bb','c':'ccc'})
sample_b.lazyload( 'd' , lazyloaded_function , "dddd" )
print "sample_a"
print sample_a
print "sample_a.d = %s" % sample_a.d
print sample_a
print "====="
print "sample_b"
print sample_b
print "sample_b['d'] = %s" % sample_b['d']
print sample_b
这不只是记忆吗?记忆是个更好的术语。我用的是金字塔法的物化。我将调整问号和标签。