Pythonic List Iteration

Bor*_*vor 1 python iteration django

我有一个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  
Run Code Online (Sandbox Code Playgroud)

考虑到python的奇迹,感觉好像有一种内置的功能可以为你做到这一点.但是,我浏览了一下itertools库,并没有跳出来作为简化此操作的方法.

所以我的问题是,有更多的pythonic方式执行上述操作吗?

Mar*_*ers 5

是的,调用该函数functools.reduce().使用它operator.or_():

import operator
from functools import reduce

final_qs = reduce(operator.or_, qs_list)
Run Code Online (Sandbox Code Playgroud)

reduce()将第一个值qs_list传递给第一个参数的值operator.or_,有效地执行qs_list[0] | qs_list[1].然后它接受该结果,加上下一个值qs_list并再次应用第一个参数,依此类推,直到qs_list完成为止.

对于qs_list4个元素,归结为:

or_(or_(or_(qs_list[0], qs_list[1]), qs_list[2]), qs_list[3])
Run Code Online (Sandbox Code Playgroud)

或相当于:

qs_list[0] | qs_list[1] | qs_list[2] | qs_list[3]
Run Code Online (Sandbox Code Playgroud)

但是对于任何长度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
Run Code Online (Sandbox Code Playgroud)