一日一技:在Python里面实现链式调用

简介: 一日一技:在Python里面实现链式调用

摄影:产品经理大学路的泰国菜

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

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

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

运行效果如下图所示:

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

目录
相关文章
|
5月前
|
Python 缓存
Python ChainMap:链式映射的妙用与实战解析
【4月更文挑战第1天】Python中的`collections`模块提供了一个名为`ChainMap`的类,它实现了多个字典的链式查找。`ChainMap`将多个字典组织成一个逻辑上的单一字典,允许你像操作单个字典一样来访问这些字典。当在`ChainMap`中查找一个键时,它会按照字典被添加的顺序从前向后依次查找,直到找到匹配的键为止。如果找不到,就会抛出`KeyError`。
|
缓存 数据库 Python
一日一技:在Python里面实现链式调用
一日一技:在Python里面实现链式调用
64 0
|
4天前
|
数据挖掘 索引 Python
Python数据挖掘编程基础3
字典在数学上是一个映射,类似列表但使用自定义键而非数字索引,键在整个字典中必须唯一。可以通过直接赋值、`dict`函数或`dict.fromkeys`创建字典,并通过键访问元素。集合是一种不重复且无序的数据结构,可通过花括号或`set`函数创建,支持并集、交集、差集和对称差集等运算。
14 9
|
4天前
|
前端开发 Python
Python编程的面向对象(二)—类的多态
Python编程的面向对象(二)—类的多态
12 7
|
3天前
|
存储 开发者 Python
探索Python编程的奥秘
【9月更文挑战第29天】本文将带你走进Python的世界,通过深入浅出的方式,解析Python编程的基本概念和核心特性。我们将一起探讨变量、数据类型、控制结构、函数等基础知识,并通过实际代码示例,让你更好地理解和掌握Python编程。无论你是编程新手,还是有一定基础的开发者,都能在这篇文章中找到新的启示和收获。让我们一起探索Python编程的奥秘,开启编程之旅吧!
|
4天前
|
人工智能 小程序 API
文字转语音神器+Python编程搞定语音报时小程序
文字转语音神器+Python编程搞定语音报时小程序
11 2
|
4天前
|
Python
Python编程的循环结构小示例(二)
Python编程的循环结构小示例(二)
|
5天前
|
存储 设计模式 算法
Python编程练习小结
Python编程练习小结
10 1
|
5天前
|
开发者 索引 Python
7个提升python编程的小技巧
7个提升python编程的小技巧
18 0
7个提升python编程的小技巧
|
4天前
|
算法 Python
Python编程的函数—内置函数
Python编程的函数—内置函数
下一篇
无影云桌面