python中如何实现链式调用

作者:kingname 时间:2021-05-06 08:42:29 

我们在使用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()

python中如何实现链式调用

直接对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()

python中如何实现链式调用

从图中可以看出,现在已经不会报错了。那么回到最开始的问题,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)

运行效果如下图所示:

python中如何实现链式调用

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

来源:https://mp.weixin.qq.com/s/LmTO6WL6stw3S5-WWJ6s6A

标签:python,链式,调用
0
投稿

猜你喜欢

  • python 采用paramiko 远程执行命令及报错解决

    2021-01-23 19:17:16
  • python 基于pygame实现俄罗斯方块

    2021-07-22 15:47:23
  • Python装饰器用法与知识点小结

    2023-11-16 00:45:02
  • Python为何不能用可变对象作为默认参数的值

    2022-11-30 13:42:04
  • Django 浅谈根据配置生成SQL语句的问题

    2023-05-10 07:48:23
  • python list 合并连接字符串的方法

    2021-12-18 09:35:30
  • WEB2.0网页制作标准教程(7)CSS学习入门

    2007-12-13 13:12:00
  • Python 中的反转字符串reversed(),切片

    2021-05-27 15:03:06
  • 边框样式的写法总结

    2009-01-18 13:00:00
  • 24式加速你的Python(小结)

    2023-09-25 10:25:24
  • Python计算已经过去多少个周末的方法

    2023-03-10 11:40:52
  • 如何更快更好地调试ASP程序代码?

    2009-11-23 20:13:00
  • python获取命令行参数实例方法讲解

    2022-12-10 06:40:32
  • Python使用grequests(gevent+requests)并发发送请求过程解析

    2023-08-14 16:29:01
  • 也来谈谈”完美”跨域

    2008-12-19 12:34:00
  • Python基于time模块求程序运行时间的方法

    2023-07-27 15:59:03
  • Python中typing模块的具体使用

    2022-03-25 13:02:08
  • 解决jupyter加载文件失败的问题

    2022-07-21 19:17:05
  • python基础之迭代器与生成器

    2022-02-20 07:07:54
  • Oracle 下医嘱执行函数

    2009-03-02 10:49:00
  • asp之家 网络编程 m.aspxhome.com