【问题标题】:Why does the order of these statements with 'and' change the output even with parentheses?为什么这些带有“和”的语句的顺序即使带有括号也会改变输出?
【发布时间】:2023-03-28 16:14:01
【问题描述】:

所以我正在解决 Codecademy 上循环的一些代码挑战。一个特别的问题让我很烦恼。这是根据 Codecademy 的设置:

编写一个名为 delete_starting_evens() 的函数,它有一个名为 lst 的参数。 该函数应该从 lst 的前面删除元素,直到列表的前面不是偶数。然后该函数应返回 lst。 例如,如果 lst 从 [4, 8, 10, 11, 12, 15] 开始,那么 delete_starting_evens(lst) 应该返回 [11, 12, 15]。 即使列表中的每个元素都是偶数,也要确保您的函数正常工作!

现在这段代码工作正常,正如我所料:

def delete_starting_evens(lst):
  while (len(lst) > 0) and (lst[0] % 2 == 0):
    lst.pop(0)
  return lst

print(delete_starting_evens([4, 8, 10, 11, 12, 15]))
print(delete_starting_evens([4, 8, 10]))

虽然此代码产生错误,但我不确定原因:

def delete_starting_evens(lst):
  while (lst[0] % 2 == 0) and (len(lst) > 0):
    lst.pop(0)
  return lst

print(delete_starting_evens([4, 8, 10, 11, 12, 15]))
print(delete_starting_evens([4, 8, 10]))`

错误是:

Traceback (most recent call last):
  File "script.py", line 8, in <module>
    print(delete_starting_evens([4, 8, 10]))
  File "script.py", line 3, in delete_starting_evens
    while (lst[0] % 2 == 0) and (len(lst) > 0):
IndexError: list index out of range

【问题讨论】:

  • 如果在lst 为空时尝试使用lst[0],则会出现异常。这就是为什么你应该先检查len(lst)

标签: python


【解决方案1】:

这就是and的短路行为:

x and y

计算第一个假操作数并且不计算任何其他操作数,因为结果已经很清楚了。因此,如果x 为假,则不会评估y,因此将避免评估y 引发的任何错误。见the docs

这就是为什么你会经常看到:

if lst and lst[0]:  # if lst is empty, lst[0] will not be tried
    # ... 

但不是:

if lst[0] and lst:  # lst[0] raises error before lst is tested
    # ... 

顺便说一句,有一个库函数适合您的确切用例,即itertools.dropwhile

from itertools import dropwhile

def delete_starting_evens(lst):
    return list(dropwhile(lambda x: not x%2, lst))

【讨论】:

  • 我不确定你答案的最后一部分是什么意思,但是谢谢!
  • 这只是您代码的简写;-) “在条件(不是 x%2)成立时从 lst 中删除元素,保持休息”
【解决方案2】:

这是因为当 python 解释器评估你的表达式时:

while (lst[0] % 2 == 0) and (len(lst) > 0):

它总是首先检查第一条语句。在这种情况下,即使列表可能为空,它也会对 lst[0] 执行检查。第一段代码首先检查len(lst) &gt; 0,这就是没有错误的原因。

【讨论】:

    猜你喜欢
    • 2021-03-11
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-06
    相关资源
    最近更新 更多