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

时间:2017-05-24 03:53:36

标签: python python-2.7 loops

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

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)的方法来满足要求?

3 个答案:

答案 0 :(得分:3)

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

  

明确比隐含更好。

     

可读性计数。

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

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
    ...

这很好,因为它说“如果我没有失败最多次,继续前进。这比一个好一点:

number_of_failures = 0
while True:
    ...
    if this_is_a_failure_case:
        number_of_failures += 1
    ...
    if number_of_failures == MAX_FAILURES: #you could use >= but this isn't necessary
        break

隐藏退出案例。有时在中间退出循环是完全正常的,但在你的情况下,在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中,我们喜欢直接而有意义。计数器可能听起来很笨重,但如果你说得好(毕竟你算错了,对吧?)你安全地处于Pythonic代码领域。

答案 1 :(得分:2)

使用if语句对您的尝试进行编号似乎很简单。它很简单,而且(我的眼睛)很容易阅读,符合您的Pythonic标准。

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 /失败条件时迭代尝试次数,如果你想计算总数,而不仅仅是失败,你可以将failure_no +=1设置为正确在while之后,而不是在else区块内。

注意:您可以轻松地在逃生中添加通知:

例如

    if failure_no == max_fails:
      print 'Maximum number of failures reached'
      break

答案 2 :(得分:1)

E.g。您可以使用if语句并在n次尝试后引发错误。 您只需要limitcounter

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) 

...