为什么python`any`返回bool而不是值?

问题描述 投票:43回答:7

andor返回他们评估的最后一个元素,但为什么不是Python的内置函数any

我的意思是这样实现自己很容易,但我仍然想知道为什么。

def any(l):
    for x in l:
        if x:
            return x
    return x

编辑:

要添加到下面的答案,这里是你们强大的皇帝在同一个邮件列表中的实际引用:

是否总是返回True和False或第一个faling / passing元素?在博客之前我也玩过它,并且意识到最终的情况(如果序列是空的或者所有元素都没有通过测试)永远不能令人满意:如果参数是可迭代的bool,则选择None感觉很奇怪,并且如果参数是非bool对象的可迭代,那么选择False会感觉很奇怪。

Guido van Rossum(主页:http://www.python.org/~guido/

python function internal
7个回答
45
投票

这个问题出现在2005年Python开发人员的邮件列表中,当时Guido Van Rossum建议将anyall添加到Python 2.5中。

Bill Janssen requested认为他们被实施为

def any(S):
    for x in S:
        if x:
            return x
    return S[-1]

def all(S):
    for x in S:
        if not x:
            return x
    return S[-1]

Raymond Hettinger,他实施了anyallresponded专门解释了为什么anyall不像andor那样:

随着时间的推移,我得到了关于这些和其他itertools食谱的反馈。没有人反对这些食谱或Guido版本中的真/假返回值。

Guido的版本符合任何/所有谓词的正常期望。此外,它避免了人们目前使用Python的“和”和“或”的独特实现所遇到的错误/混淆。

归还最后一个元素并不邪恶;它只是奇怪的,意外的,非显而易见的。抵制这个变得棘手的冲动。

邮件列表在很大程度上是同意的,只留下今天看到的实现。


20
投票

andor可以通过他们总是返回其中一个操作数的方式明智地定义。但是,anyall无法明确地定义为从输入序列返回一个值:具体来说,当列表为空时,它们不能这样做。在这种情况下,anyall目前都有明确定义的结果:any返回False,all返回True。您将被迫有时返回一个布尔值,有时会从序列返回一个项目,这会产生令人不快和令人惊讶的界面。简单而一致的好多了。


5
投票

我问同样的问题on python-ideas,并被告知原因是any()all()需要在序列为空时返回一个值,这些值必须是FalseTrue。这对我来说似乎是一个微弱的争论。

这些函数现在不能改变,但我认为它们会更有用,并且如果它们返回了他们遇到的第一个真正的或者虚假的值,那么它们推广的andor运算符的更好的类比。


3
投票

由于历史原因,andor的行为存在。

在Python有三元运算/条件表达式之前,如果要在条件上使用值,则使用andor。可以使用条件表达式语法重写任何此类表达式:

true_val if condition else false_val

从本质上讲,它们有两个功能,并且由于兼容性原因,它们没有被更改。

这不是使其他操作超负荷的原因。 any似乎应该告诉你条件对于任何项是否为真,这是一个布尔值,所以它应该返回一个bool


1
投票

启动Python 3.8,并引入assignment expressions (PEP 572):=算子),我们可以明确地捕获any表达式的证人或all表达式的反例:


引用PEP description的几个例子:

if any(len(long_line := line) >= 100 for line in lines):
  print("Extremely long line:", long_line)
if all((nonblank := line).strip() == '' for line in lines):
  print("All lines are blank")
else:
  print("First non-blank line:", nonblank)

0
投票

显而易见,any的值可能是False或输入中的一个值。此外,大多数用途看起来像

tmp = any(iterable)
if tmp:
   tmp.doSomething()
else:
   raise ValueError('Did not find anything')

这是Look Before You Leap因此unpythonic。相比于:

next(i for i in iterable if i).doSomething()
# raises StopIteration if no value is true

andor的行为在历史上可用作当时不可用的条件表达式的插入。


0
投票

Any返回一个布尔值,因为它有效地将其参数视为bool列表,然后再考虑它们是否为真。它返回它评估的元素,但这恰好是一个bool。

您想什么时候使用您的any版本?如果它在bool列表中,那么你已经有了正确的答案。否则你只是在防范None,可能表达为:

filter(lambda x: x != None, l)[0]

要么:

[x for x in l if x != None][0]

这是一个更明确的意图陈述。

© www.soinside.com 2019 - 2024. All rights reserved.