【问题标题】:How to exit an if clause如何退出 if 子句
【发布时间】:2011-01-05 09:28:04
【问题描述】:

过早退出if 子句有哪些方法?

有时我在编写代码时想在 if 子句中添加 break 语句,但要记住这些语句只能用于循环。

我们以下面的代码为例:

if some_condition:
   ...
   if condition_a:
       # do something
       # and then exit the outer if block
   ...
   if condition_b:
       # do something
       # and then exit the outer if block
   # more code here

我可以想到一种方法来做到这一点:假设退出情况发生在嵌套的 if 语句中,将剩余的代码包装在一个大的 else 块中。示例:

if some_condition:
   ...
   if condition_a:
       # do something
       # and then exit the outer if block
   else:
       ...
       if condition_b:
           # do something
           # and then exit the outer if block
       else:
           # more code here

问题在于更多的退出位置意味着更多的嵌套/缩进代码。

或者,我可以编写我的代码以使 if 子句尽可能小,并且不需要任何退出。

有人知道退出if 子句的好方法吗?

如果有任何关联的 else-if 和 else 子句,我认为退出会跳过它们。

【问题讨论】:

  • 第二个代码示例——你知道elif吗?
  • “或者,我可以编写我的代码以使 if 子句尽可能小,并且不需要任何退出。” ——当然这将是最好的行动方案。 :-)
  • @Craig McQueen:我愿意,但是说我想让代码在条件语句之间执行?例如。 if a: #stuff; #stuff_inbetween; if b: #stuff; 中间代码依赖于not a,但不依赖于b
  • 你好,请不要忘记elifstackoverflow.com/a/2069680/7045119

标签: python control-flow


【解决方案1】:

(此方法适用于ifs、多个嵌套循环和其他您无法轻松使用break 的构造。)

将代码包装在自己的函数中。代替break,使用return

例子:

def some_function():
    if condition_a:
        # do something and return early
        ...
        return
    ...
    if condition_b:
        # do something else and return early
        ...
        return
    ...
    return

if outer_condition:
    ...
    some_function()
    ...

【讨论】:

  • 我很高兴添加到您的程序员技巧包中。根据我的经验,这种方法几乎在您每次想要使用向前移动的 goto 时都有效。 (它既暗示并解决了单个函数变得太大的情况)
  • 理想情况下,您可以同时实现两者,但有时您必须以良好的代码换取良好的性能。这种情况很少见,尤其是当您考虑使用 Python 时。换句话说:不要太担心函数调用开销。
  • 有一个古老的轶事:“Dennis Ritchie 鼓励模块化,他告诉所有人,函数调用在 C 中非常非常便宜。每个人都开始编写小函数并进行模块化。多年后我们发现函数调用在 PDP-11 上仍然很昂贵,而且 VAX 代码经常将 50% 的时间花在 CALLS 指令上。丹尼斯对我们撒了谎!但为时已晚;我们都被迷住了……”
  • @ephemient:这很有趣,还有更多的故事吗?我想阅读全文。
  • 这段引文来自 The Art of Unix Programming(在线faqs.org/docs/artu)一书的第 4 章。如果您以前没有阅读过,您真的应该阅读全文。
【解决方案2】:
来自goto 导入 goto,标签 如果某些条件: ... 如果条件_a: # 做一点事 # 然后退出外部 if 块 转到.end ... 如果条件_b: # 做一点事 # 然后退出外部 if 块 转到.end # 更多代码在这里 标签 .end

(请不要实际使用它。)

【讨论】:

  • +1 因为这很有趣。谷歌搜索告诉我这是一个愚人节的笑话模块。
  • 我也链接到它。点击第一个goto
  • 这让我想起了带有各种分支的汇编代码:)
  • @ehemient:啊,没注意到链接。认为这是代码突出显示。但是现在我查看了您的代码,我没有看到任何真正的突出显示..
  • 当 PHP 引入 goto 我转向 Python php.net/manual/en/control-structures.goto.php
【解决方案3】:
while some_condition:
   ...
   if condition_a:
       # do something
       break
   ...
   if condition_b:
       # do something
       break
   # more code here
   break

【讨论】:

  • 哦,嘿,我真的很喜欢这个主意。我认为这恰好解决了我最初的愿望。但是,我有一种挥之不去的感觉,认为这不是一个好的做法(因此,我将暂时保留当前接受的答案,因为它促进了良好的编码风格)。
  • 请注意,您可以保留原始 if 并将整个内容包装在 while True: 中。只需确保在末尾添加 break 声明即可!对于具有 do-while 结构的语言,这样做更符合规范:do { code that can conditionally break out } while (false);
【解决方案4】:

您可以模拟 goto 的功能,但有例外:

try:
    # blah, blah ...
    # raise MyFunkyException as soon as you want out
except MyFunkyException:
    pass

免责声明:我只是想让您注意以这种方式做事的可能性,而我绝不认为在正常情况下它是合理的。正如我在对该问题的评论中提到的那样,到目前为止,首先避免拜占庭条件的结构化代码是可取的。 :-)

【讨论】:

  • 哈哈,我喜欢这个有创意的解决方案。虽然我会遵守你的免责声明,不会使用这种时髦的代码。
  • @Roman:很高兴在 Shmoopty 的旁边添加另一个技巧——即使相比之下我觉得很顽皮。 ;-)
【解决方案5】:

可能是这个?

if some_condition and condition_a:
       # do something
elif some_condition and condition_b:
           # do something
           # and then exit the outer if block
elif some_condition and not condition_b:
           # more code here
else:
     #blah
if

【讨论】:

  • 是的,这可行。我想在我写这篇文章的时候,我的大脑有点空白 elif。虽然我认为这在我希望代码在嵌套的 if 语句之间执行的情况下不起作用。
  • 这实际上是正确的答案。为什么我看不到人推荐这个?? :)
【解决方案6】:

对于实际询问的内容,我的方法是将那些 ifs 放入一个循环中

while (True):
    if (some_condition):
        ...
        if (condition_a):
            # do something
            # and then exit the outer if block
            break
        ...
        if (condition_b):
            # do something
            # and then exit the outer if block
            break
        # more code here
    # make sure it is looped once
    break

测试一下:

conditions = [True,False]
some_condition = True

for condition_a in conditions:
    for condition_b in conditions:
        print("\n")
        print("with condition_a", condition_a)
        print("with condition_b", condition_b)
        while (True):
            if (some_condition):
                print("checkpoint 1")
                if (condition_a):
                    # do something
                    # and then exit the outer if block
                    print("checkpoint 2")
                    break
                print ("checkpoint 3")
                if (condition_b):
                    # do something
                    # and then exit the outer if block
                    print("checkpoint 4")
                    break
                print ("checkpoint 5")
                # more code here
            # make sure it is looped once
            break

【讨论】:

  • 说实话,这是最干净的解决方案。代码何时退出非常清楚 - 您不必担心函数内部的函数作用域,并且性能或逻辑债务为零。
  • 可能会考虑使用for _ in range(1): 而不是while True:。 (1) 更好地传达您对单个迭代循环的意图和 (2) 没有最后一个 break 语句退出循环(以后可能会被意外删除)
【解决方案7】:

一般来说,不要。如果您嵌套“ifs”并从中分离出来,那么您做错了。

但是,如果您必须:

if condition_a:
   def condition_a_fun():
       do_stuff()
       if we_wanna_escape:
           return
   condition_a_fun()
if condition_b:
   def condition_b_fun():
       do_more_stuff()
       if we_wanna_get_out_again:
           return
   condition_b_fun()

注意,函数不必在 if 语句中声明,它们可以提前声明;)这将是一个更好的选择,因为它可以避免以后需要重构一个丑陋的 if/then。

【讨论】:

  • 感谢您的回答。我不确定“嵌套循环”是什么意思。如果您指的是我提到的关键字“break”,我只是试图通过将 if-exit 与循环出口的存在进行比较来激发我对 if-exit 的搜索。另外,我不确定您的代码如何解决问题,因为我的示例将if condition_aif condition_b 嵌套在if some_condition 中。我希望能够突破if some_condition
  • 人们想要嵌套 if 并破坏它们的原因可能不是因为他们做错了,而是可能是因为他们想编写干净简单且 DRY 的代码。简单的情况是当条件_a和条件_b都满足时程序需要执行x(),并且只需要对条件_a执行y(),并且只需要对条件_b执行z()。并且编码器拒绝多次写入 x()
【解决方案8】:

还有另一种方法不依赖于定义函数(因为有时对于小代码 sn-ps 可读性较差),不使用额外的外部 while 循环(这可能需要在 cmets 中特别注意乍一看可以理解),不使用 goto (...),最重要的是,让您保持外部缩进级别,这样您就不必开始嵌套内容。

if some_condition:
   ...
   if condition_a:
       # do something
       exit_if=True # and then exit the outer if block
if some condition and not exit_if: # if and only if exit_if wasn't set we want to execute the following code
   # keep doing something
   if condition_b:
       # do something
       exit_if=True # and then exit the outer if block
if some condition and not exit_if:
   # keep doing something

是的,这还需要再次查看可读性,但是,如果代码的 sn-ps 很小,则不需要跟踪任何不会重复的 while 循环,并且在了解中间 if 的用途之后,它是易于阅读,所有内容都集中在一个位置并具有相同的缩进。

而且效率应该很高。

【讨论】:

    【解决方案9】:

    实际上,您所描述的是 goto 语句,这些语句通常被大量平移。你的第二个例子更容易理解。

    但是,更清洁的仍然是:

    if some_condition:
       ...
       if condition_a:
           your_function1()
       else:
           your_function2()
    
    ...
    
    def your_function2():
       if condition_b:
           # do something
           # and then exit the outer if block
       else:
           # more code here
    

    【讨论】:

      【解决方案10】:

      所以我知道你正在尝试突破外部 if 代码块

      if some_condition:
          ...
          if condition_a:
             # do something
             # and then exit the outer if block
             ...
          if condition_b:
             # do something
             # and then exit the outer if block
      # more code here
      

      解决这个问题的一种方法是,您可以在外部 if 块中测试错误条件,然后隐式退出代码块,然后使用 else 块将其他 if 嵌套到 做点什么

      if test_for_false:
          # Exit the code(which is the outer if code)
      
      else:
          if condition_a:
              # Do something
      
          if condition_b:
              # Do something
      

      【讨论】:

        【解决方案11】:

        这是处理此问题的另一种方法。它使用单个项目 for 循环,使您能够只使用 continue。它可以防止不必要地无缘无故地拥有额外的功能。此外还消除了潜在的无限 while 循环。

        if something:
            for _ in [0]:
                # Get x
                if not x:
                    continue
        
                # Get y
                if not y:
                    continue
        
                # Get z
                if not z:
                    continue
        
                # Stuff that depends on x, y, and z
        

        【讨论】:

          【解决方案12】:

          在没有其他方法的情况下唯一可以应用它的是elif,如下例所示

          a = ['yearly', 'monthly', 'quartly', 'semiannual', 'monthly', 'quartly', 'semiannual', 'yearly']
          # start the condition
          if 'monthly' in b: 
              print('monthly') 
          elif 'quartly' in b: 
              print('quartly') 
          elif 'semiannual' in b: 
              print('semiannual') 
          elif 'yearly' in b: 
              print('yearly') 
          else: 
              print('final') 
          

          【讨论】:

            【解决方案13】:

            在 if 条件中使用 return 会将您从函数中返回, 这样您就可以使用 return 来打破 if 条件。

            【讨论】:

            • 他想打破 if not exit 函数
            猜你喜欢
            • 2015-03-06
            • 2022-07-28
            • 1970-01-01
            • 2015-12-08
            • 2014-12-27
            • 1970-01-01
            • 2013-11-26
            • 2013-06-15
            • 1970-01-01
            相关资源
            最近更新 更多