2016-02-28 21 views
0

下面的代碼工作,但看起來非常醜陋。我正在尋找更多pythonic的方式來寫同樣的事情。更好/更pythonic的方式來處理多個返回值的函數的結果

目標: 對返回多個值的函數的結果進行響應。

實例功能

def myfilterfunc(mystr): 
    if 'la' in mystr: 
     return True, mystr 
    return False, None 

返回true和一個字符串(如果字符串cointains 「LA」),或假而已。

在第二個功能,我路過myfilterfunc作爲可選參數

def mymainfunc(mystr,filterfunc=None): 

此功能填補了returnlist。 如果沒有給出函數,則結果不會被過濾並按原樣添加。 如果給出了過濾器函數,如果過濾器函數返回 True,則會添加返回的字符串。 (這只是一個例子,將 輕鬆地與一個返回值的工作,但我試圖讓systax 適合更復雜的設置)

if filterfunc: 
    tmp_status,tmp_string = filterfunc(mystr[startpos:nextitem]) 
    if tmp_status: 
     returnlist.append(tmp_string) 
    else: 
     returnlist.append(mystr[startpos:nextitem]) 

任何想法,我怎麼可以這樣寫,而無需使用臨時變量來存儲函數的返回值?

完全 「工作」 的測試代碼如下

def string2list(mystr,splitlist,filterfunc=None): 
    returnlist = [] 
    startpos = 0 
    nextitem = -1 
    matched = True 
    while matched: 
     matched = False 
     for sub in splitlist: 
      if startpos == 0: 
       tmpi = mystr.find(sub) 
      else:  
       tmpi = mystr.find(sub,startpos + 1) 
      if (tmpi > 0) and ((nextitem < 0) or (nextitem > tmpi)): 
       nextitem = tmpi 
       matched = True 
     if filterfunc: 
      tmp_status,tmp_string = filterfunc(mystr[startpos:nextitem]) 
      if tmp_status: 
       returnlist.append(tmp_string) 
     else: 
      returnlist.append(mystr[startpos:nextitem]) 
     startpos = nextitem 
     nextitem = -1 
    return returnlist 

def myfilterfunc(mystr): 
    if 'la' in mystr: 
     return True,mystr 
    return False,''  


splitlist = ['li','la'] 
mytext = ''' 
li1 
li2 
li3 
fg4 
fg5 
fg6 
la7 
la 
la 
tz 
tz 
tzt 
tz 
end 
''' 



print string2list(mytext,splitlist) 
print 
print string2list(mytext,splitlist,myfilterfunc) 
+1

爲什麼你不只是返回字符串或'None'? – jonrsharpe

+0

這是一個非常簡單的編程示例,我試圖找出如何處理兩個返回值,而不是以後要做的非常複雜的事情...... – 576i

+0

然後請給出一個更具代表性的示例,請參見[mcve]。 – jonrsharpe

回答

1

如果這將經常發生,你可以分解出uglyness:

def filtered(f, x): 
    if f: 
     status, result = f(x) 
     return result if status else x 
    else: 
     return x 

使用像

returnlist.append(filtered(filterfunc, mystr[startpos:nextitem])) 

使如果您有許多類似的可選過濾器,代碼仍然可讀。這是有效的,因爲在Python中,函數/閉包是第一類公民,您可以像其他值一樣傳遞它們。

不過,如果邏輯約爲一直在增加(使用過濾或未經過濾)爲什麼不只是寫過濾器返回輸入,而不是(False, "")失敗的情況下?

這將使得代碼更容易理解......

returnlist.append(filterfunc(mystr[startpos:nextitem])) 
+0

因爲我將此作爲兩個值的返回示例來學習Python語法(來自Pascal like語言),並且我仍在嘗試找到正確的方法來執行操作。此外,當我返回一個值(字符串或None)並使用'returnlist.append(filterfunc(mystr [startpos:nextitem]))'並且不會將可選的* filterfunc *傳遞給主函數時,代碼會崩潰* NoneType不可調用* – 576i

+0

多一點評論,我並不總是添加。如果* filterfunc *返回False(或None),我不會添加。我添加了,如果* filterfunc *返回了一個或者沒有* filterfunc *被給定。 – 576i

+0

我解決了可選的* filterfunc *問題,如果filterfunc是None:filterfunc = lambda x:x',那麼一行附加工作... – 576i

0

我認爲有兩個好你這個問題的方法是不使用兩個返回值涉及。

第一個是簡單地返回一個布爾值,而不是一個字符串。如果你的過濾器總是返回一個字符串(如果第一個值是True),它會一直返回未經修改的字符串。這種方法可以讓你避免使用臨時值都:

if filterfunc: 
    if filterfunc(mystr[startpos:nextitem]): 
     returnlist.append(mystr[startpos:nextitem]) 

(注意,我建議重命名filterfuncpredicate如果你走這條路線。)

如果某些filterfunc可能會返回與在某些情況下通過的第二個值不同的第二個值,但從未使用二元組True, None。在這種方法中,您只需使用單個值作爲信號和有效載荷。如果它是None,你會忽略它。如果是其他任何東西,你就使用它。這確實需要一個臨時變量,但只有一個(並且它不那麼難看)。

if filterfunc: 
    result = filterfunc(mystr[startpos:nextitem]) 
    if result is not None: 
     returnlist.append(result) 
+0

謝謝。這是示例代碼,我試圖看看如何使用返回多個值的可選函數。我的主要目標是看看它是否可以在Python中運行良好並避免臨時變量。 – 576i

相關問題