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

时间:2012-04-16 19:24:58

标签: python function internal

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

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

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

编辑:

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

  

是否总是返回True和False或第一次faling / pass   元件?在博客之前我也玩过这个,并意识到了   结束案例(如果序列为空或者所有元素都未通过测试)   永远不能令人满意的工作:选择没有感觉很奇怪,如果   参数是一个可迭代的bools,如果选择False会觉得很奇怪   参数是一个可迭代的非bool对象。

     

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

7 个答案:

答案 0 :(得分:44)

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

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]

执行anyallresponded的Raymond Hettinger专门解决了为什么anyall不采取行动{{1} }和and

  

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

     

Guido的版本符合任何/所有人的正常期望   谓语。此外,它避免了人们的那种错误/混乱   目前使用Python"和"的独特实现经验和   "或"

     

返回最后一个元素并不邪恶;它只是奇怪,出乎意料,而且   非显而易见的。抵制这个变得棘手的冲动。

邮件列表在很大程度上得到了同意,现在就像你今天看到的那样实现了。

答案 1 :(得分:20)

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

答案 2 :(得分:5)

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

这些函数现在不能改变,但我认为它们会更有用,并且如果它们返回第一个真正的或者是假的,它们会更好地模拟它们概括的Trueand运算符。 - 他们遇到的价值。

答案 3 :(得分:3)

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

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

true_val if condition else false_val

基本上,它们有两个功能超载,出于兼容性原因,它们没有被更改。

这是超载其他操作的原因。 any似乎应该告诉你条件是否适用于任何项,这是一个布尔值,因此它应该返回bool

答案 4 :(得分:0)

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

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

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

或:

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

更明确的意图声明。

答案 5 :(得分: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的行为在历史上非常有用,可作为当时不可用的条件表达式的插入。

答案 6 :(得分:0)

Python 3.8开始,并引入assignment expressions (PEP 572):=运算符),我们可以替代地显式捕获any表达式的 witness 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)