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

Tra*_*ish 9 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
Run Code Online (Sandbox Code Playgroud)

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

小智 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]
Run Code Online (Sandbox Code Playgroud)

所以像这样使用:

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
           ]
Run Code Online (Sandbox Code Playgroud)


MSe*_*ert 8

您可以通过使用刚刚True在第一种情况下返回的函数my_fun2par1在第二种情况下实际比较结果的函数来动态选择条件函数:

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)]
Run Code Online (Sandbox Code Playgroud)

或者通过用生成器表达式替换外部循环,以防par1不是空字符串:

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]
Run Code Online (Sandbox Code Playgroud)

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

  • 谢谢,是的,我同意.DRY和可读性之间存在细微差别. (2认同)