什么时候循环中断

时间:2013-01-09 21:45:01

标签: python loops

我有一个while循环:

def setWorkDays(dayNameList):
            workDays = []
            while self.count > 0: #continue loop until all 5 work days have been filled or the loop breaks at the end 
                for day in dayNameList: #iterate over days, adding days to work days if they are not free days, AL days, preferred days, or free Saturdays 
                    if day in self.freeDays or day in self.alDays or (day == 'Saturday' and self.satOff is True):
                        continue
                    elif day in self.programDays:
                        workDays.append(day)
                        self.count -= 1
                    elif self.preferredDay is not None and day in self.preferredDay:
                        continue
                    else:
                        workDays.append(day)
                        self.count -= 1
                if self.preferredDay not in self.workDays: #if iteration completes, 5 work days have not been filled, and the preferred day has not been added, add the preferred day 
                    workDays.append(self.preferredDay)
                    self.count -=1
                return workDays

循环背后的想法是self.count命中0的第二个循环终止。这是修改self.count的唯一函数。然而,我得到了奇怪的结果,循环似乎持续了至少1个计数太长,因为程序在某些情况下为self.count输出-1。这应该发生吗? while循环不应该终止第二个self.count命中零,还是必须先完成for循环?我应该在self.count递减之后添加条件逻辑,检查self.count是否为零,如果是,则会中断?这似乎是while循环的目的......

4 个答案:

答案 0 :(得分:2)

一旦while循环的条件不再为真,它就不会在中间循环中自动退出;它只是检查每个循环开始时的条件。如果您想提前退出,则需要明确break(或者从函数中执行其他非本地操作,例如return或在raise之外执行except处理程序循环)。

看起来你要做的就是尽早退出for循环,如果self.count达到0,那么就没有办法直接这样做了。每次递减时都必须检查。

但是,你真的根本不需要self.count。您将它完全递减到appendworkDays的相同位置。所以,检查一下你是否还有5个。换句话说,每个self.count -= 1变为:

if len(workDays) >= 5: break

实际上有一种方法可以在Python中做你想做的事情:使用生成器而不是列表。如果您yield每个值而不是将其附加到list,然后在结尾处返回list,则只需在获得5个条目后停止迭代生成器。

例如:

def setWorkDays(dayNameList):
    while self.count > 0: #continue loop until all 5 work days have been filled or the loop breaks at the end 
        for day in dayNameList: #iterate over days, adding days to work days if they are not free days, AL days, preferred days, or free Saturdays 
            if day in self.freeDays or day in self.alDays or (day == 'Saturday' and self.satOff is True):
                continue
            elif day in self.programDays:
                yield day
            elif self.preferredDay is not None and day in self.preferredDay:
                continue
            else:
                yield day
        if self.preferredDay not in self.workDays: #if iteration completes, 5 work days have not been filled, and the preferred day has not been added, add the preferred day 
            yield day

workDays = [setWorkDays(dayNameList) for _ in range(5)]

通常,你甚至不需要list,你需要做的就是迭代它。为此,您可以这样做:

for workDay in (setWorkDays(dayNameList) for _ in range(5)):

或者:

for workDay in itertools.islice(setWorkDays(dayNameList), 5):

在你理解它们之前,发电机可以做很多事情就像魔术一样 - 这通常意味着在你了解发电机之前你不应该这样做。所以,如果这对你没有意义,那就不要只是拿起来使用它。但如果它提示你学习如何编写和使用生成器函数,那就太好了!

答案 1 :(得分:1)

self.count循环中,您的减量数次while

循环只会在块的开头处中断。那么可能发生的是self.count在块的开头是正的,然后在单个块中递减到负值。

答案 2 :(得分:1)

任何语言(我知道)的while循环都不会像您期望的那样工作。

通常,while循环的格式为:

while <condition>:
  <code block>

while循环每个循环检查一次条件。它不会持续检查状况。这意味着整个代码块将在每个条件检查之间执行,除非在代码块期间执行某些控制流语句(例如continuebreakreturn)。 / p>

实际上,每个循环一次的条件检查具有性能优势(计算机不必经常评估条件)以及限制程序的cyclomatic complexity

答案 3 :(得分:1)

这似乎可以满足您的需求:

def setWorkDays(dayNameList):
     workDays = []
     for day in dayNameList:
         if day in self.freeDays or day in self.alDays or (
             day == 'Saturday' and self.satOff):
                 continue
         elif day in self.programDays:
             workDays.append(day)
             self.count -= 1
         elif self.preferredDay is not None and day in self.preferredDay:
             continue
         else:
             workDays.append(day)
             self.count -= 1
         if self.count <= 0:
              break
     else:
         if self.preferredDay not in self.workDays:
             workDays.append(self.preferredDay)
             self.count -=1
     return workDays