Pythonic方式在列表推导中使用第二个条件

时间:2017-08-14 11:22:11

标签: python if-statement list-comprehension

我们假设以下函数:

def myfun(my_list, n, par1=''):
    if par1 == '':
        new_list = [[my_fun2(i,j) for j in range(n)] for i in range(n)]
    else:
        new_list = [[my_fun2(i,j) for j in range(n)] for i in range(n) if my_fun2(i,n) == par1]
    return new_list

如您所见,根据par1,有两种不同的情况。我不喜欢第3行和第5行几乎相同,并且不遵循DRY(不要重复自己)原则。如何改进此代码?

3 个答案:

答案 0 :(得分:8)

这可能有效:

new_list = [[my_fun2(i,j) for j in range(n)] for i in range(n) if par1 == '' or my_fun2(i,n) == par1]

所以这样使用:

def myfun(my_list, n, par1=''):
    return [
               [my_fun2(i,j) for j in range(n)]
               for i in range(n) if par1 == '' or my_fun2(i,n) == par1
           ]

答案 1 :(得分:8)

您可以使用在第一种情况下仅返回True的函数和在第二种情况下实际将my_fun2结果与par1进行比较的函数动态选择条件函数:< / p>

def myfun(my_list, n, par1=''):
    if par1 == '':
        cond = lambda x, y: True
    else:
        cond = lambda i, n: my_fun2(i, n) == par1
    return [[my_fun2(i,j) for j in range(n)] for i in range(n) if cond(i,n)]

或者,如果par1不是空字符串,则用generator expression替换外部循环:

def myfun(my_list, n, par1=''):
    if par1 == '':
        outer = range(n)
    else:
        # a conditional generator expression
        outer = (i for i in range(n) if my_fun2(i,n) == par1)
    return [[my_fun2(i,j) for j in range(n)] for i in outer]

但是,不要让DRY让函数更难以阅读,维护或调试。我个人认为你的方法很好(可能更快),你可能不应该做任何改变。

答案 2 :(得分:1)

为什么不使用过滤器?

from operator import eq
def myfun(my_list, n, par1=''):
    new_list = ([my_fun2(i,j) for j in range(n)] for i in range(n))
    if par1 != '':
        new_list = filter(eq(par1),new_list)
    return list(new_list)