gpt4 book ai didi

python - 如何将 SQLAlchemy 的 @hybrid_property 装饰器与 Werkzeug 的 cached_property 装饰器结合起来?

转载 作者:行者123 更新时间:2023-12-01 04:18:15 25 4
gpt4 key购买 nike

如何将这两者结合起来:

Werkzeug 的 @cached_property 装饰器:http://werkzeug.pocoo.org/docs/0.11/utils/#werkzeug.utils.cached_property

SQLAlchemy 的 @hybrid_property 装饰器: http://docs.sqlalchemy.org/en/latest/orm/extensions/hybrid.html#sqlalchemy.ext.hybrid.hybrid_property

用例:我有一个混合属性,它执行相当昂贵的计算,如果结果被缓存也没关系。我尝试用它们包装一个测试函数,无论哪一个先出现,它们都提示第二个装饰器不可调用

最佳答案

这有点棘手,因为 cached_propertyhybrid_property 都希望包装一个方法并返回一个属性。您最终会扩展其中之一或两者。

我能想到的最好的事情就是这个。它基本上内联了 cached_property 的逻辑进入hybrid_property__get__。请注意,它会缓存实例的属性值,但不会缓存类的属性值。

from sqlalchemy.ext.hybrid import hybrid_property

_missing = object() # sentinel object for missing values


class cached_hybrid_property(hybrid_property):
def __get__(self, instance, owner):
if instance is None:
# getting the property for the class
return self.expr(owner)
else:
# getting the property for an instance
name = self.fget.__name__
value = instance.__dict__.get(name, _missing)
if value is _missing:
value = self.fget(instance)
instance.__dict__[name] = value
return value


class Example(object):
@cached_hybrid_property
def foo(self):
return "expensive calculations"
<小时/>

起初我以为你可以简单地使用 functools.lru_cache而不是cached_property。然后我意识到您可能需要特定于实例的缓存,而不是由实例索引的全局缓存,这正是 lru_cache 提供的。没有用于缓存每个实例的方法调用的标准库实用程序。

为了说明 lru_cache 的问题,请考虑这个简单版本的缓存:

CACHE = {}

class Example(object):
@property
def foo(self):
if self not in CACHE:
CACHE[self] = ... # do the actual computation
return CACHE[self]

这将为您的程序生成的每个 Example 实例存储 foo 的缓存值 - 换句话说,它可能会泄漏内存。 lru_cache 更聪明一些,因为它限制了缓存的大小,但是如果某些值超出了缓存,您可能最终会重新计算它们。更好的解决方案是将缓存的值附加到它们所属的 Example 实例,就像 cached_property 所做的那样。

关于python - 如何将 SQLAlchemy 的 @hybrid_property 装饰器与 Werkzeug 的 cached_property 装饰器结合起来?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34057756/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com