2017-08-14 53 views
9

假設如下功能:使用第二個條件列表Python的方式推導

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(不要重複自己)原則。這個代碼如何改進?

+0

檢查我的回答,我沒有你的確切功能,因此很難對其進行測試在同樣的環境,但我認爲它應該做的伎倆 – dhdavvie

+0

這將是很好的瞭解你真正嘗試解決。 – ferdy

回答

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 
      ] 
+0

您也可以將歸還合併到第2行,但那真的取決於您 – dhdavvie

+1

儘管這是一種可能的解決方案,但我認爲可讀性不太好,所以它缺少python禪的「可讀性計數」規則。恕我直言,級聯列表理解應該分解。 – ferdy

+0

小調:你不需要理解(或括號內)的反斜槓:) – MSeifert

8

你可以動態地選擇條件功能通過使用只是在第一種情況下返回True一個函數和一個實際在第二種情況下將my_fun2結果與par1進行比較:

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)] 

,或在情況下par1generator 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

謝謝,是的,我同意。 DRY和可讀性之間有一條細線。 – Trarbish

+0

@Trarbish很好,這也是一個關於性能的問題(不僅關於可讀性)。你的方法會比我的生成器表達方法更快(這可能是這裏提到的最快而非DRY方法)。 – MSeifert

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) 
+1

我知道,對於未來和Python3來說,列表解析是一種更好的方式,可以用來替代使用map,filter和reduce。 – madtyn

+0

python 3中的過濾器創建一個生成器,這就是爲什麼返回值被list() –

相關問題