@reify 每次调用都会执行数据库查询?

Posted

技术标签:

【中文标题】@reify 每次调用都会执行数据库查询?【英文标题】:@reify executes database queries every time called? 【发布时间】:2021-08-19 04:22:42 【问题描述】:

基于this comment关于reify,

它的作用类似于@property,只是该函数只被调用一次;之后,该值被缓存为常规属性。这使您可以在不可变的对象上创建惰性属性。

我有这个自定义的 reify 类:

class reify(object):
    def __init__(self, wrapped):
        self.wrapped = wrapped

    def __get__(self, inst):
        if inst is None:
            return self
        val = self.wrapped(inst)
        setattr(inst, self.wrapped.__name__, val)
        return val

它的用法如下:

@reify
def user_details(self, user_id):
    try:
        # function that executes db query, returns dict
        return user_details_from_id(self._dbconn, user_id)
    except Exception as e:
        pass

很明显,我们可以通过 name = self.user_details.get("name") 来使用它。

这按预期工作,但不确定这是缓存结果还是每次调用时都执行查询,我该如何确认?我的意思是这个实现是否正确? (没有数据库控制台)

【问题讨论】:

也许将执行数据库查询的函数替换为向控制台打印内容的函数? 当然可以,但我认为真正的问题是这个实现是否正确? 我建议的是一种验证方法。 【参考方案1】:

def user_details(self, user_id) 这样的签名有太多的参数,@reify 甚至@property 都无法支持。应该是def user_details(self)。然后reify 装饰器将修改属性self.user_details 以在实例的持续时间内返回相同的值。请注意,它不是全局的,而是针对每个实例的,因为它使用self。要确认它正在缓存,您只需将 print 语句放在 user_details 函数中,以确认每个实例仅调用一次。

【讨论】:

是的,我确实创建了一个简单的 API 服务器来获取一些用户数据,它只发出一个请求,所以非常感谢您的回复

以上是关于@reify 每次调用都会执行数据库查询?的主要内容,如果未能解决你的问题,请参考以下文章

每次我从 Python 库路径调用 .egg 时,AWS Glue 作业都会崩溃

VS连接Access数据库--连接字符串及执行查询语句的方法(增删改查,用户名查重,根据用户获取密码查询)

分布式缓存遇到的问题汇总

C#编写的,每次点击和数据库相关的查询功能的时候都会出现错误,别人在他电脑上运行都好好的,请问

pl/sql连接Oracle不管执行啥语句都会重复执行这条语句,永不停止,怎么办呀

MySql慢查优化之路|01-执行计划