在Python中n次失败后退出无界循环的最佳方法是什么?

在Python中n次失败后退出无界循环的最佳方法是什么?,python,python-2.7,loops,Python,Python 2.7,Loops,我是Python的新手。我想知道在n失败后如何退出无界的循环。对我来说,使用计数器似乎是不和谐的。 这是我的代码: while(True): #get trigger state trigState = scope.ask("TRIG:STATE?") #check if Acq complete if( trigState.endswith('SAVE') ): print 'Acquisition complete. Writing into fil

我是Python的新手。我想知道在
n
失败后如何退出无界的循环。对我来说,使用计数器似乎是不和谐的。 这是我的代码:

while(True):
#get trigger state  
    trigState = scope.ask("TRIG:STATE?")
    #check if Acq complete 
    if( trigState.endswith('SAVE') ):
      print 'Acquisition complete. Writing into file ...\n'
      #save screen
      #rewrite in file  

    #check if trigger is still waiting 
    elif( trigState.endswith('READY') ):
      print 'Please wait ...\n'   
    #if trigger neither in SAVE nor in READY mode  
    else:
      #THIS IS FAILURE!!!
      print 'Failure: k tries remaining'

    #wait for several seconds before next iteration 
    time.sleep(2) 
请注意,循环必须是无界的-它可以任意迭代多次,直到超过尝试次数

是否有一种优雅(或至少是pythonic)的方法来满足这些要求?

要成为“pythonic”,您需要编写符合的代码,相关规则如下:

显式比隐式好

可读性很重要

您应该明确说明允许的失败次数或剩余的失败次数。在前一种情况下:

for number_of_failures in range(MAX_FAILURE):
    ...
表达了这种意图,但很笨拙,因为每次循环都不一定会失败,所以在计算成功的次数时,你必须被扭曲,这会影响可读性。你可以选择:

number_of_failures = 0
while number_of_failures < MAX_FAILURES:
    ...
    if this_is_a_failure_case:
        number_of_failures += 1
    ...
这隐藏了退出案例。有时在中间退出循环是完全正确的,但是在你的情况下,在N次故障之后中止对你想做的事情非常重要,条件应该在while循环条件下。

您还可以根据剩余故障数重新表述:

failures_remaining = MAX_FAILURES
while failures_remaining > 0:
    ...
    if this_is_a_failure_case:
        failures_remaining -= 1
    ...
如果您喜欢函数式编程,可以摆脱循环并使用尾部递归:

def do_the_thing():
    def try_it(failures_remaining = MAX_FAILURES):
        ...
        failed = ....
        ...
        try_it(failures_remaining-1 if failed else failures_remaining)

    try_it()

但依我看,这并不是真正的进步。在Python中,我们喜欢直接而有意义。计数器可能听起来很笨重,但如果你把事情说得很好(毕竟你在计算失败次数,对吧?),你就安全地进入了Python代码的领域。

例如,你可以使用
if
语句,并在n次尝试后引发错误。 您只需要一个
限制
和一个
计数器

while(True):
#get trigger state  
limit = 5
counter = 0
trigState = scope.ask("TRIG:STATE?")
#check if Acq complete 
if( trigState.endswith('SAVE') ):
  print 'Acquisition complete. Writing into file ...\n'
  #save screen
  #rewrite in file  

#check if trigger is still waiting 
elif( trigState.endswith('READY') ):
  print 'Please wait ...\n'   
#if trigger neither in SAVE nor in READY mode  
else:
  #THIS IS FAILURE!!!
  counter +=1
  print 'Failure: ', limit - counter ,' tries remaining'
  if k => limit: raise RuntimeError('too many attempts')


#wait for several seconds before next iteration 
time.sleep(2) 

使用
if
语句对您的尝试进行编号对于您的目的来说似乎非常简单。它很简单,而且(在我看来)容易阅读,这符合你的标准

while
循环中,您可以执行以下操作:

failure_no = 0 
max_fails = n #you can substitute an integer for this variable
while:
  #...other code
  else:
    failure_no += 1
    if failure_no == max_fails:
      break
  print 'Failure: '+str(max_fails - failure_no)+' tries remaining'
这只会在满足
else
/失败条件的情况下重复尝试次数,如果您想计算贯穿运行的总数,而不仅仅是失败,您可以将
失败\u no+=1
放在
while
之后,而不是放在
else
块中

注意:你可以很容易地在你的逃生舱内放置一个通知:

乙二醇


使用计数器有什么问题?听起来这正是你所需要的。另外,你三次提到“无限”这个词,一次在标题中,两次在问题文本中。你能澄清你所说的无限是什么意思吗?如果你有办法退出循环,它怎么可能是无限的呢?确实,当失败次数少于n次时,循环会运行,也许我们永远不会遇到n次失败,但这并不意味着循环一定是无限的,只是无限的。“你这个词还有别的意思吗?”雷托尔,你说得对。这个词应该是无界的。使用计数器并不是非音速的——事实上,它让其他程序员非常清楚你的意图。我会说只要使用计数器不,你们的答案很好,我使用计数器。但我不知道我应该接受哪个答案。注意,Python中不推荐递归,因为它的堆栈限制相对较小,并且不会将递归函数优化为迭代函数。关于这个问题:
failure_no = 0 
max_fails = n #you can substitute an integer for this variable
while:
  #...other code
  else:
    failure_no += 1
    if failure_no == max_fails:
      break
  print 'Failure: '+str(max_fails - failure_no)+' tries remaining'
    if failure_no == max_fails:
      print 'Maximum number of failures reached'
      break