在Python里面实现链式调用

本文介绍了Django模型查询中链式调用filter方法的实现原理,探讨了如何通过返回self实现类似功能,并模拟了查询条件的缓存过程。Django在实际操作中会延迟执行数据库查询,直到需要数据时才执行,从而提高效率。
摘要由CSDN通过智能技术生成

来源:未闻Code

我们在使用Django的models查询数据库时,可以看到有这种写法:

form app.models import XXX 
query = XXX.objects.all() 
query = query.filter(name=123, age=456).filter(salary=999)

在这种写法里面,query对象有一个filter方法,这个方法的返回数据还可以继续调用filter方法,可以这样无限制地调用下去。

这种写法是怎么实现的呢?

如果我们直接写一个类的方法,看看能不能这样调用:

class Query: 
def filter(self): 
pass 
query = Query() 
query.filter().filter()
7019c19da545def28e07623d96dd2520.png

直接对query.filter()返回的结果再调用一次filter,就会导致报错了。这是因为在没有显式写return语句的时候,方法会返回None,而None对象是没有所谓的filter方法的。

那么什么东西有filter方法呢?显然我们的query对象有filter方法。那么如何让这个方法返回自身这个对象呢?

这个时候,我们就要看看我们在定义类方法的时候,总会写的的第一个参数self了。几乎每个类方法里面都会有它。大家只知道在类里面调用类方法的时候可以用self.xxx(),在调用类属性的时候可以用self.yy,那么有没有思考过,这个东西如果单独使用会怎么样呢?

实际上,self指的就是这个类实例化成一个对象以后,这个对象自身。而这个对象显然是有filter方法的。所以我们修改一下filter方法,让它返回self:

class Query: 
    def filter(self): 
        return self 
query = Query() 
query.filter().filter()
531caaf891351fd68c63b33cc8700819.png

从图中可以看出,现在已经不会报错了。那么回到最开始的问题,Django里面的链式调用传入查询参数是如何实现的呢?

实际上这里涉及到一个惰性查询的问题。

当我们不停调用.filter()方法的时候,Django会把这些查询条件全部缓存起来,只有当我们需要获取结果,或者查询满足条件的数据有多少条时,它才会真正地连接数据库去查询。

所以我们这里要模拟这个环境,把查询条件缓存起来。

那么为了获取调用方法时传入的参数名,我们就要使用**kwargs参数。这个参数可以接受所有的key=value形式的参数:

class Query(): 
    def __init__(self): 
        self.query_condition = {} 

    def filter(self, **kwargs): 
        self.query_condition.update(kwargs) 
        return self 

query = Query() 
a = query.filter(name='kingname').filter(age__gt=15, address='yyyyyy').filter(salary=99999) 
print(query.query_condition)

运行效果如下图所示:

bef8217359f941c6b6f9d326722597a8.png

在真正需要输出结果的时候,再使用这些缓存的条件,去数据库中查询结果即可。

-------- End --------

cd1ca884412266d5d927b30ad9f3c4bd.png
精选资料

回复关键词,获取对应的资料:

关键词资料名称
600《Python知识手册》
md《Markdown速查表》
time《Python时间使用指南》
str《Python字符串速查表》
pip《Python:Pip速查表》
style《Pandas表格样式配置指南》
mat《Matplotlib入门100个案例》
px《Plotly Express可视化指南》
精选视频

可视化: Plotly Express

财经: Plotly在投资领域的应用 | 绘制K线图表

排序算法: 汇总 | 冒泡排序 | 选择排序 | 快速排序 | 归并排序 | 堆排序 | 插入排序 | 希尔排序 | 计数排序 | 桶排序 | 基数排序

63544644dea9f28368849d37d1a2d821.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值