为啥 Python 内置的“all”函数为空的可迭代对象返回 True?

Posted

技术标签:

【中文标题】为啥 Python 内置的“all”函数为空的可迭代对象返回 True?【英文标题】:Why Python built in "all" function returns True for empty iterables?为什么 Python 内置的“all”函数为空的可迭代对象返回 True? 【发布时间】:2012-08-12 08:39:51 【问题描述】:

我知道这是有充分理由的,但我想知道是什么原因?

>>> print all([])
True

如果 all() 旨在检查可迭代对象上的每个项目是否评估为“True”,并且我们知道空列表的评估结果为 False

>>> bool([])
False

那么为什么 all() 对空列表返回 True 呢?

我已经阅读了文档,并且我知道实现

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

但问题是为什么不呢?

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

这有逻辑吗?如果您有已完成任务的列表

today_todo_status = [task.status for task in my_todo if task.date == today]
can_i_go_home = all(today_todo_status)

好的,在上面的假设示例中,如果我没有任务,那么我就可以回家了。

但还有其他情况,我不认为 all() 是为待办事项列表制作的。哈哈

编辑 >

【问题讨论】:

正如所指出的,所有状态同时为真和假,空集不包含任何内容。对您的示例真正有意义的不是all(today_todo_tasks),而是any(map(lambda task: task.status != DONE, today_todo_tasks)) Reason for "all" and "any" result on empty lists的可能重复 C# Linq All 扩展方法的行为方式相同。 我认为@MarkMikofski 提到的副本对为什么提出问题有更清晰的解释。 【参考方案1】:

这表示为“对于 S 中的所有 X,X 为真”。如果 S 为空,则没有 X。但是,真值陈述仍然为 True,因为对于所有 X,X 都是真的……只是没有任何 X!

这里是解释using logic。

考虑两个集合 A 和 B,其中 A+B 是两个集合的并集。

如果 any(A+B) = True -> any(A) 或 any(B) = True 但我们不能断言 any(A)=True 或 any(B)=True。

如果 any(A+B) = False -> any(A) = False 且 any(B) = False。

如果 all(A+B) = True -> all(A)=True 并且 all(B)=True

如果 all(A+B) = False -> all(A)=False 或 all(B)=False 但我们不能断言 all(A)=False 或 all(B)=False。

现在代替 B,让我们将空集 Ø 添加到 A。我们想提出 逻辑使得添加空集不会改变 all() 或 any(),因为 A+Ø=A。

any(A+Ø) = any(A) 或 any(Ø)

any(Ø) 必须为 False,因此如果 any(A) 为 True,则 any(A+Ø) 为 True,并且 如果 any(A) 为 False,则 any(A+Ø) 为 False。

所有(A+Ø)=所有(A)和所有(Ø)

如果 all(A) 为 True,则 all(A+Ø) 为 True。因此,all(Ø) 为真。

【讨论】:

正如这个答案(正确)暗示的那样,all() 函数旨在模仿数学中的全称量词,当应用于空集时它被定义为真。请参阅en.wikipedia.org/wiki/Vacuous_truth 讨论为什么会出现这种情况,以及为什么许多人(包括 OP)感觉不对。 空洞的真相会导致错误; if all(nuclear_sub.has_been_destroyed for nuclear_sub in fleet): launch_doomsday_device() 现在我们退役最后一个潜艇的那一天会发生什么??【参考方案2】:

all()(记录为“如果可迭代对象的所有元素都为真(或者如果可迭代对象为空),则返回 True。”)等价于以下内容:

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

由于没有元素,所以会跳过循环,返回True

【讨论】:

这只是引出问题的循环逻辑。 “它是这样定义的,因为这是它的定义方式”并不是一个真正的答案...... 我在文档上看到了.. 但它没有回答问题。为什么不检查 iterable 是否为 False 并返回它? @sr2222 它显示了all() 运作背后的逻辑。通过展示该方法返回True 除非其中有False 元素,我们可以理解为什么它为空列表返回True @rochacbruno 你为什么要先检查它是否是False?包含所有 True 元素的列表可以为空; 0 个元素的集合仍然是不包含 False 元素的集合。 问题不在于它是如何运作的,而在于它为什么要这样运作。 @Interrobang 实际上提供了一个解释。就好像 rochacbruno 问道:“为什么地球围绕太阳旋转,”你回答,“因为轨道被定义为围绕另一个物体移动的物体”,而 Interrobang 回答说,“重力”。【参考方案3】:

假设all([])False

那么,对于所有非空列表Aall(A + []) 也应该是False

all(A + []) = all(A) and all([])
            = all(A) and False
            = False

自从A + [] = A,我们就知道了

all(A + []) = all(A) for any non empty list A

但是,all(A) 可能是 True(例如,A = [True]

因此,

对于所有非空列表Aall(A + []) 也应该是False

这自相矛盾。结果,第一个假设是错误的,

all([])True

【讨论】:

【参考方案4】:

因为所有元素都是True。当没有元素时,你可以说'所有元素都是......任何东西'

【讨论】:

【参考方案5】:

这来自数学逻辑。

“空集的元素一切都为真”(http://en.wikipedia.org/wiki/Empty_set)

另见http://en.wikipedia.org/wiki/Vacuous_truth

【讨论】:

【参考方案6】:

ELI5 版本。

获取数字列表

L = [1,2,3,4,6]

all([isintance(l, int) for l in L])

all 的定义方式是,使其成为False 的唯一方法是提供at least 一个非整数。

类似地,any 的定义方式是,要使其成为True,您只需要at-least 一个正整数即可。

由于all()any() 的补集,一个必须是True,另一个必须是False

【讨论】:

【参考方案7】:

在测试条件时,我们希望始终将第一个元素添加到列表中。例如,如果我们只想将小于最小数字或大于最大数字的数字添加到列表中,我们可以这样做:

def addToList(less,num):
    if less:
        if any( num >= savedNum for savedNum in numbers):
            print(' is not less'.format(num))
            return
    elif any( num <= savedNum for savedNum in numbers):
        print(' is not greater'.format(num))
        return

    numbers.append(num)


numbers = []
doLess = True
doMore = False
addToList(doLess,5) #numbers is empty, but will be added
addToList(doLess,2)
addToList(doLess,7)
addToList(doMore,15)
addToList(doMore,9)
print(numbers)

输出:

7 is not less [5, 2]
9 is not greater [5, 2, 15]
[5, 2, 15]

【讨论】:

以上是关于为啥 Python 内置的“all”函数为空的可迭代对象返回 True?的主要内容,如果未能解决你的问题,请参考以下文章

内置函数

内置函数

Python基础之内置函数和递归

python内置函数

内置函数和匿名函数

Python内置函数之all()