为啥 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
。
那么,对于所有非空列表A
,all(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]
)
因此,
对于所有非空列表
A
,all(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?的主要内容,如果未能解决你的问题,请参考以下文章