51

由此处的讨论提示

文档all为和的行为提出了一些等效的代码any

等效代码的行为是否应该被视为定义的一部分,或者实现可以以非短路方式实现它们?

这是来自 cpython/Lib/test/test_builtin.py 的相关摘录

def test_all(self):
    self.assertEqual(all([2, 4, 6]), True)
    self.assertEqual(all([2, None, 6]), False)
    self.assertRaises(RuntimeError, all, [2, TestFailingBool(), 6])
    self.assertRaises(RuntimeError, all, TestFailingIter())
    self.assertRaises(TypeError, all, 10)               # Non-iterable
    self.assertRaises(TypeError, all)                   # No args
    self.assertRaises(TypeError, all, [2, 4, 6], [])    # Too many args
    self.assertEqual(all([]), True)                     # Empty iterator
    S = [50, 60]
    self.assertEqual(all(x > 42 for x in S), True)
    S = [50, 40, 60]
    self.assertEqual(all(x > 42 for x in S), False)

def test_any(self):
    self.assertEqual(any([None, None, None]), False)
    self.assertEqual(any([None, 4, None]), True)
    self.assertRaises(RuntimeError, any, [None, TestFailingBool(), 6])
    self.assertRaises(RuntimeError, all, TestFailingIter())
    self.assertRaises(TypeError, any, 10)               # Non-iterable
    self.assertRaises(TypeError, any)                   # No args
    self.assertRaises(TypeError, any, [2, 4, 6], [])    # Too many args
    self.assertEqual(any([]), False)                    # Empty iterator
    S = [40, 60, 30]
    self.assertEqual(any(x > 42 for x in S), True)
    S = [10, 20, 30]
    self.assertEqual(any(x > 42 for x in S), False)

它不会做任何事情来强制执行短路行为

4

4 回答 4

64

行为是有保证的。我提供了一个补丁,它最近被接受并合并,所以如果你获取最新的资源,你会看到短路行为现在被明确地强制执行。

git clone https://github.com/python/cpython.git
grep Short-circuit cpython/Lib/test/test_builtin.py
于 2013-02-14T01:29:39.380 回答
12

文档说

“如果可迭代的任何元素为真,则返回 True。如果可迭代为空,则返回 False。等效于: ”(强调我的)...

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False

如果any没有短路,则与发布的代码不等效,因为发布的代码明显短路。例如,您可能会消耗比您想要的更多的发电机。鉴于此,我说短路行为是有保证的

可以对 进行完全相同的论证all

于 2013-02-06T13:28:41.233 回答
11

万一你登陆这里寻找“做任何/所有总是短路?”

他们确实这样做了,但有一个问题:使用列表推导可能会让您看起来像是在覆盖短路行为:

def hi():
    print('hi')
    return True

>>> any(hi() for num in [1, 2, 3, 4])
hi

>>> any([hi() for num in [1, 2, 3, 4]])
hi
hi
hi
hi

列表推导在 any() 之前执行。

(注意:这并不能回答 OP 非常不同的问题。这是我在搜索“任何全短路 python”时出现的唯一 stackoverflow 页面。)

于 2018-12-03T19:48:38.873 回答
3

它必须短路,因为它可以被赋予一个未绑定的迭代。如果它没有短路,那么这将永远不会终止:

any(x == 10 for x in itertools.count())
于 2013-02-06T13:39:55.090 回答