我有一个Django Querysets列表,我想将它组合成一个Query。合并两个Queryset的标准方法是执行操作:newQ = Q1 | Q2
,我想对列表中的所有元素执行该操作,以形成单个Queryset对象。
使用for循环这非常简单,例如:
for qs in qs_list:
if final_qs not in locals():
final_qs = qs
else:
final_qs = final_qs | qs
鉴于python的奇迹,感觉好像有一种内置的功能可以为你做到这一点。但是,我查看了itertools
库,没有任何内容可以简化为简化此操作。
所以我的问题是,有更多的pythonic方式执行上述操作吗?
答案 0 :(得分:5)
是的,该功能称为functools.reduce()
。与operator.or_()
:
import operator
from functools import reduce
final_qs = reduce(operator.or_, qs_list)
reduce()
将第一个值设为qs_list
,将其传递给第一个参数operator.or_
,有效执行qs_list[0] | qs_list[1]
。然后它接受该结果,加上qs_list
中的下一个值并再次应用第一个参数,依此类推,直到完成qs_list
。
对于包含4个元素的qs_list
,可归结为:
or_(or_(or_(qs_list[0], qs_list[1]), qs_list[2]), qs_list[3])
或等同于:
qs_list[0] | qs_list[1] | qs_list[2] | qs_list[3]
但降低适用于任何长度的qs_list
> 0(对于长度为1的列表,返回第一个值而不应用第一个参数)。
请注意,您对if final_qs not in locals()
的使用非常简单;不要那样做。您可以使用来自final_qs
的初始qs_list[0]
来编写循环:
final_qs = qs_list[0]
for qs in qs_list[1:]:
final_qs |= qs