2013-01-09 125 views
0

我有一个while循环:什么时候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循环的目的...

+5

一个'while'循环背后的想法是,是检查的条件,执行下面的代码块整,然后再检查等 – Volatility

+2

也许是一个格式错误,但是目前,由于最后的返回,这个代码总是只在单个循环迭代之后返回。 –

+0

是的,这是基于假设while循环可能会终止在for循环的中间某处,一旦计数命中零。休息是我希望终止的最后一点。除了每次减量self.count之外,是否还有其他工具可以获得我想要的结果? – user1427661

回答

2

A while只要条件不再为真,循环不会在循环中自动退出;它只是检查每个循环开始时的状态。如果您想早日退出,则需要明确地(或者执行其他非本地操作,例如从函数returnraiseexcept循环外的处理程序)。

好像你正在试图做的是走出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): 

很多东西,发电机可以做到觉得神奇,直到你了解他们,这往往意味着你不应该做,直到你了解发电机。所以,如果这对你没有意义,不要只是把它拿起来使用它。但如果它提示你学习如何编写和使用生成器函数,太棒了!

+0

感谢您的彻底解答。我必须明确检查,而不是使用workDays length作为count的代理,因为程序最终会有其他函数递减count属性。 – user1427661

+0

@ user1427661:查看编辑后的版本。我不指望你了解它是如何工作的 - 但如果你了解它是如何工作的,它可能会帮助你解决真正的问题。 – abarnert

1

您在您的while循环中递减了几次self.count

循环只会在块的开始处断开。所以可能发生的是self.count在块的开始处为正,然后在单个块中递减为负值。

1

A while以任何语言(我知道)循环都不会按照您期望的方式工作。

一般而言一个while回路具有以下格式:

while <condition>: 
    <code block> 

的每循环while循环检查一次的条件。它不会不断检查情况。这意味着整个代码块将在每个条件检查之间执行,除非在代码块中执行某些控制流程语句(如continue,breakreturn)。

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

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

原始循环可以跨越多个星期,而这个不能。对于给定的示例代码,这只是意味着,在任何情况下,如果您提前返回一个不完整的答案,原始代码将永远循环,这是一个改进。但是如果OP的真实代码需要在数周内完成,那将是一个不同的故事。 – abarnert