【问题标题】:Why doesn't Python throw an Index Error for the following case?为什么 Python 在以下情况下不抛出索引错误?
【发布时间】:2014-01-15 06:43:24
【问题描述】:

我在一个涉及布尔运算的 "if" 条件语句中遇到了这个 Python 场景。每当条件中出现索引错误时,Python 会将其视为 False,而不是抛出 Index Error。这种行为的原因是什么。

示例场景:

lst = [3, 4, 23, 5, 25, 76]
n = len(lst)
if n < 5 and lst[6] > lst[2]:
    print True
print False

输出:

False

如您所见,为什么 Python 返回 False?,我原以为它会抛出 Index Error。谁能解释一下幕后发生的事情。

【问题讨论】:

  • 因为if的后半部分是否为假不需要评估...(它可以短路)例如将其更改为n &lt; 20...或更改andor

标签: python algorithm python-2.7 if-statement boolean


【解决方案1】:

在您的示例中,n = 6,因此 n 不小于 5。Python 短路布尔逻辑,因此跳过了 and 表达式的后半部分。

【讨论】:

    【解决方案2】:

    and 在 Python 中使用 short-circuit evaluation,这意味着如果它的第一个参数的计算结果为 false(如 n &lt; 5 所做的那样),那么第二个参数将不被计算,因为整个表达式的结果 must 在那一点上是假的。因此,lst[6] &gt; lst[2] 永远不会被评估。

    现在让我们试试&amp;,它不会短路:

    >>> lst = [3, 4, 23, 5, 25, 76]
    >>> n = len(lst)
    >>> if (n < 5) & (lst[6] > lst[2]):
    ...     pass
    ... 
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    IndexError: list index out of range
    

    这给出了您预期的结果。

    【讨论】:

    • @JonClements &amp; 在布尔上下文中的行为类似于 and,只是它不会短路,这是这里的重要区别。当然or 也可以。
    【解决方案3】:

    当结果已知时,Python 会尽快停止评估条件。在您的示例中,n &lt; 5False,因此如果是连词 (and),则无需评估第二部分 - 它与它的评估结果无关,目前已知整个表达式为False

    如果第一个条件是Trueor 表达式也是如此,因此:

    if not (n >= 5 or lst[6] <= lst[2]):
    

    也不会扔。

    这种机制称为Short-circuit evaluation

    【讨论】:

      【解决方案4】:

      if 语句中使用and 就像编写两个if 语句,一个在另一个中:

      if n < 5:
          if lst[6] > lst[2]:
              print True
      

      在这种情况下,如果 n 不少于 5,那么为什么第二个 if 不会引发错误是显而易见的:它永远不会被执行。由于其他人已经描述了短路功能,将它们组合成一个 if 具有完全相同的行为。

      顺便说一句,or 的“长”写法是这样的:

      # if x == 0 or 1/x > 0.01: print True
      if x == 0:
          print True
      elif 1/x > 0.01:
          print True
      

      这里我们通过仅在 x 不为零时计算 1/x 来避免除以零(错误)。这同样适用于带有or 的单if 版本。由于x == 0 在这种情况下为真,表达式的真值通过计算该项即可知道,因此不需要计算第二项。

      【讨论】:

      • 虽然这个答案对原始问题的作者很有用,但应该注意,这种分解为嵌套 if 语句的方法不适用于涉及 'and' 和 'or 的嵌套和/或连接表达式'。在某个阶段,最好学习使用短路运算符的解释,这些运算符仅在可能对整体表达式结果产生影响的情况下评估其 RHS 上的内容(因此可能忽略副作用,例如原文)。
      • 是的,我并不是真的建议他们应该这样写(尽管有时,当一个人 if 的条件变得太粗糙时,这是有道理的);这只是帮助理解。
      • 嗨@kindall,很抱歉造成混乱。我的评论不是针对您,而是针对 Arunprasath Shankar 和未来的读者,旨在提醒他们在发展的某个阶段坚持理解短路解释。 :-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-23
      • 2011-04-17
      • 1970-01-01
      • 2018-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多