以下代码应该短路:
any([True, 2+2, False, 2/0]) all([True, 2+2, False, 2/0])
但对于其中的每一个,我都会得到一个ZeroDivisionError: division by zero。
ZeroDivisionError: division by zero
我是不是漏掉了什么?为什么会出现错误?
你的代码之所以会抛出 ZeroDivisionError,是因为 any 和 all 并不会阻止列表的完全求值。在 Python 中,列表是在传递给函数之前就已经构建好的,这意味着:
ZeroDivisionError
any
all
any()
all()
2/0
any 和 all 只对传入的迭代器执行短路,但传递的列表已经是一个已构造好的对象。因此,短路行为仅适用于迭代期间的元素,而不是在构造列表时。
对于你的代码:
any([True, 2+2, False, 2/0]) # 列表在调用 `any()` 前被完全求值。
True
2+2
False
为了实现短路,应该改用生成器表达式,因为生成器表达式是惰性求值的,每次只生成一个元素,避免提前计算所有元素。
以下是修复代码的方法:
any(x for x in [True, 2+2, False, 2/0]) # 生成器表达式
或更明确地:
any(x for x in (True, 2+2, False, 2/0)) # 使用元组,避免提前构造列表
对于 any: - 一旦找到第一个 True,即停止计算。 - 如果 True 是第一个元素,那么 2+2 和 2/0 都不会被求值。
对于 all: - 一旦找到第一个 False,即停止计算。 - 如果 False 是第一个元素,那么 2/0 不会被求值。
修复后的代码:
# 生成器表达式短路示例 print(any(x for x in [True, 2+2, False, 2/0])) # 不会触发错误,输出 True print(all(x for x in [True, 2+2, False, 2/0])) # 不会触发错误,输出 False