在 while 循环布尔值中切换 `and` 语句的边

switching sides of `and` statement in while loop boolean

我的问题是我想编写一个函数 newlist,它将 list 个数字作为参数。然后它 returns 一个基于参数的新列表。新列表包含与原始列表相同的值,直到达到数字 7。

我的有效代码:

def newlist(mylst):
    newlst = []
    idx = 0
    while (idx < len(mylst)) and (mylst[idx] != 7):
        newlst.append(mylst[idx])
        idx += 1
    return newlst

现在,当我像这样切换 and 语句的两侧时:

while (mylst[idx] != 7) and (idx < len(mylst)):

它告诉我这是错误的,当将列表作为参数传递时,索引是 超出范围。我的问题是为什么它与我开始的 and 语句的哪一侧有所不同?我认为布尔值只有在两个语句都为真时才为真,而不管顺序如何?

不同之处在于 and 运算符使用短路。这意味着如果第一个操作数为假,则不计算第二个操作数。

在以下内容中:

(idx < len(mylst)) and (mylst[idx] != 5)

第一个操作数是(idx < len(mylst))。这将检查 idx 是否在范围内。如果是,则计算第二个操作数,它使用 idx 作为 mylst 的索引。但如果不是,则计算停止并且表达式的结果为 False。这样,它永远不会索引越界,因为第一个操作数保护了第二个操作数的评估。

第二个版本是:

(mylst[idx] != 5) and (idx < len(mylst))

在这里,操作数被颠倒了。因此,如果 idx 超出范围,它仍会尝试将其用作 mylst 的索引,从而导致错误。

所以这两个版本有非常明显的区别。第一个版本在尝试将其用作索引之前安全地检查 idx 是否在范围内,而第二个版本则没有。