Python的短路行为是否全部显式?

时间:2013-02-06 13:16:57

标签: python short-circuiting language-specifications

讨论here

提示

docsallany

的行为建议了一些等效代码

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

以下是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 个答案:

答案 0 :(得分:39)

保证行为。我贡献了一个patch,最近被接受并且merged,所以如果您获取最新的来源,您会看到现在明确强制执行了短路行为。

git clone https://github.com/python/cpython.git
grep Short-circuit cpython/Lib/test/test_builtin.py

答案 1 :(得分:12)

文档说

  

“如果iterable的任何元素为true,则返回True。如果iterable为空,则返回False。 EQUIVALENT TO:”(强调我的)...

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

如果any未发生短路,则对发布的代码不会 EQUIVALENT ,因为发布的代码明显短路。例如,您可以消耗比您想要的更多的生成器。鉴于此,我说保证短路行为

all可以使用完全相同的参数。

答案 2 :(得分:1)

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

any(x == 10 for x in itertools.count())

答案 3 :(得分:0)

这是我搜索“所有短路python”时出现的唯一堆栈溢出页面

因此:如果您着陆在这里寻找简单的“是否/总是总是短路?”

他们做到了,但是有一个陷阱:使用列表理解可以使其似乎,就像您要覆盖短路行为一样:

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

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

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

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