2016-06-10 47 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) 

由于逐行读取将节省用于保存行的存储内存。