为什么Python的any/all函数不返回找到的对象?

3
Python中的andor运算符返回值,而不是TrueFalse,这对于像以下这样的事情非常有用:
x = d.get(1) or d.get(2) or d.get(3)

这将使x成为d [1]d [2]d [3]中存在的值。这有点像在函数式语言中具有加性Maybe monad。

我一直希望Python的any()函数更像一个重复的or。我认为它会有意义返回它找到的对象,例如:

any([None, None, 1, 2, None]) == 1
any(notnull_iterator) = try: return next(notnull_iterator); except: return None

对于all()同样也是如此。在我看来,这个改变完全向后兼容,并且增强了API的一致性。

有人知道之前是否有讨论过这个话题吗?


实际上,在您的示例中,如果d[1]是Falsey值,它将处理到d[2]等。在这种情况下,为了安全起见,您可以使用x = d.get(1, d.get(2, d.get(3))),但不幸的是,这不会短路。 - John La Rooy
没错,但通常情况下,我发现我的数据结构中填充了我的自定义对象,它们从未为“None”。 - Thomas Ahle
2个回答

5

我想你正在寻找

first = lambda s: next((x for x in s if x), None)

e.g.

first([None, None,1, 2,None]) # 1

关于"为什么"的问题,可以在这里找到答案。


2
>>> from functools import partial
>>> my_any = partial(reduce, lambda x, y:x or y)
>>> my_any([None, None, 1, 2, None])
1

>>> my_all = partial(reduce, lambda x, y:x and y)
>>> my_all([0, 0, 1, 2, 0])
0

在上面的示例中,my_all([]) 会引发异常。但是,您可以轻松地提供一个默认值。
>>> my_all([], "Foo")
'Foo'

我知道我可以自己实现它们。只是在标准库中拥有这个功能会很好,并且似乎不会使API更重。甚至可能减轻负担。尽管all([])的情况有些棘手。 - Thomas Ahle
@ThomasAhle,在这种情况下,您可以指定一个默认值,因此选择适合您需求的True或False值。 - John La Rooy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接