2016-06-10 52 views
4

總共python初學者在這裏。Pythonic打破循環的方式

我有以下函數,它檢查從某些輸入派生的字符串是否存在於文本文件中。它循環遍歷文本文件的每一行,以查看是否找到完全匹配。

我必須在找到匹配後立即跳出循環,避免不必要的循環。

下面是代碼:

def DateZoneCity_downloaded_previously(Order_Date,ZoneCity): # function to check if a given DateZoneCity 
                    # combination had already been completely downloaded 
    string_to_match = Order_Date.strftime('%Y/%m/%d') + "-" + ZoneCity[0] + "-" + ZoneCity[1] 
    with open(Record_File) as download_status: 
     DateZoneCity_exists = False 
     for line in download_status: 
      if string_to_match in line: 
       DateZoneCity_exists = True      # if match found, then set "DateZoneCity_exists" to True 
       break           # and break out from the [for line in download_status:] loop 
     if DateZoneCity_exists: return True 
    download_status.close() 

我正在尋找一個更簡潔,Python的方式來構造代碼。有什麼我可以做得更好嗎?爲了消除對「DateZoneCity_exists」和第二個If語句的需求?的

+1

這屬於[代碼評論](https://codereview.stackexchange.com/)。 –

+0

對不起,我應該做些什麼?我應該移動線程,我不知道該怎麼做。 –

+0

@Chinmay以下是您可能需要考慮的幾篇文章:[Stack Overflow用戶代碼評論指南](http://meta.codereview.stackexchange.com/questions/5777/a-guide-to-code-審查堆棧溢出用戶)和[在向代理推薦代碼審查時要小心](http://meta.stackoverflow.com/a/260427/4428725) –

回答

6

這感覺就像一個情況:any將是最好的解決辦法:

# Function to check if a given DateZoneCity 
def DateZoneCity_downloaded_previously(Order_Date, ZoneCity): 
    # Combination had already been completely downloaded 
    string_to_match = Order_Date.strftime('%Y/%m/%d') + "-" + ZoneCity[0] 
                 + "-" + ZoneCity[1] 
    with open(Record_File) as download_status: 
     return any((string_to_match in line) for line in download_status) 

注意,在這種情況下,將在負收益False,而不是當前的實現,它會返回None,還要注意它發現一個積極的結果後立即跳出循環,因此它不需要循環遍歷整個文件。

+0

不錯。非常簡潔,非常感謝。 –

4

只是return代替break

def DateZoneCity_downloaded_previously(Order_Date,ZoneCity): 
    """Check if a given DataZoneCity combination had already been downloaded.""" 
    string_to_match = Order_Date.strftime('%Y/%m/%d') + "-" + ZoneCity[0] + "-" + ZoneCity[1] 
    with open(Record_File) as download_status: 
     for line in download_status: 
      if string_to_match in line: 
       return True 
    return False # No match found. 
+0

哦,據我瞭解,退貨聲明也將立即做出突破的工作,避免未來的循環,我說得對嗎? –

+1

是的,這是正確的。 – Adriano

+0

非常感謝您的先生 –

3

根據您的文本文件是多麼大,你可以讀入一個字符串,只是使用(更容易,往往快於閱讀和檢查每行線):

if string_to_match in open(Record_File).read(): 
    return True 

在您的例子:

def DateZoneCity_downloaded_previously(Order_Date,ZoneCity):     
    string_to_match = Order_Date.strftime('%Y/%m/%d') + "-" + ZoneCity[0] + "-" + ZoneCity[1] 
    if string_to_match in open(Record_File).read(): 
     return True 
2

您不必在此處放置for循環,請參閱更新後的代碼。

def DateZoneCity_downloaded_previously(Order_Date,ZoneCity): 
    """Check if a given DataZoneCity combination had already been downloaded.""" 
    string_to_match = Order_Date.strftime('%Y/%m/%d') + "-" + ZoneCity[0] + "-" + ZoneCity[1] 
    with open(Record_File) as download_status: 
     if string_to_match in download_status.read(): 
      return True 
    return False # No match found. 
+1

我擔心,如果沒有for循環,整個文件將被加載,這將需要大量的RAM。沒有? –

+1

是的,但如果它是一個小文件。沒有必要添加for循環。 –

0

如果record_file很小,那麼你可以直接與if語句像使用in: -

def DateZoneCity_downloaded_previously(Order_Date,ZoneCity):     
    string_to_match = Order_Date.strftime('%Y/%m/%d') + "-" + ZoneCity[0] + "-" + ZoneCity[1] 
    if string_to_match in open(Record_File).read(): 
     return True 

而如果record_file較大,則你必須通過每行迭代尋找像一個匹配: -

def DateZoneCity_downloaded_previously(Order_Date, ZoneCity): 
    string_to_match = Order_Date.strftime('%Y/%m/%d') + "-" + ZoneCity[0] + "-" + ZoneCity[1] 
    with open(Record_File) as download_status: 
     return is_empty((string_to_match in line) for line in download_status) 

由於逐行讀取將節省用於保存行的存儲內存。