Python的任何/所有显式的短路行为是什么?

Joh*_*ooy 36 python short-circuiting language-specifications

这里的讨论提示

文档建议为的行为的一些等价代码allany

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

以下是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)
Run Code Online (Sandbox Code Playgroud)

它没有做任何事情来强制执行短路行为

wim*_*wim 42

这种行为是有保障的.我提供了一个补丁,最近被接受并合并,所以如果你抓住最新的资源,你会看到现在明确强制执行了短路行为.

git clone https://github.com/python/cpython.git
grep Short-circuit cpython/Lib/test/test_builtin.py
Run Code Online (Sandbox Code Playgroud)

  • 很高兴看到这个问题的时间表:2月13日问题,2月14日这个答案是[第一次修订](http://stackoverflow.com/revisions/14866380/1),2月20日[bug /补丁](http://bugs.python.org/issue17255)创建,2月21日合并,2月23日这个答案更新.由于在Stack Overflow上询问了这个问题,Python库变得更好了.(感谢你@wim当然.) (12认同)

mgi*_*son 12

文档说

"如果iterable的任何元素为真,则返回True.如果iterable为空,则返回False.等效于: "(强调我的)...

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False
Run Code Online (Sandbox Code Playgroud)

如果any没有短路,则与发布的代码不等同,因为发布的代码明显短路.例如,您可以消耗比您想要的更多的生成器.鉴于此,我说短路行为是有保证的.

可以提出完全相同的论点all.

  • @gnibbler - 我不认为会有任何反驳(除了西门在你原来的帖子上).就我而言,这是明确记录的行为...... (2认同)

msc*_*arf 7

如果您来到这里寻找“任何/所有总是短路?”

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

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
Run Code Online (Sandbox Code Playgroud)

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

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

  • 需要注意的好陷阱。在更简单的情况下 `any((a, b, c, d))` 所有 `a`,`b`,`c`,`d` 将在 any 开始之前被评估。 (2认同)
  • 这个答案(经过一些阐述)最好放在 /sf/ask/4409147011/ 上。 (2认同)