6

Python 有一个很好的 null 合并语法:

c = a or b

这设置caif ais not False, None, empty, 或0, elsec设置为b

(是的,从技术上讲,这不是空合并,它更像是bool合并,但对于这个问题来说它已经足够接近了。)

对于对象集合没有明显的方法来执行此操作,因此我编写了一个函数来执行此操作:

from functools import reduce

def or_func(x, y):
    return x or y

def null_coalesce(*a):
    return reduce(or_func, a)

这行得通,但写我自己的or_func似乎不是最理想的——肯定有一个内置的 like __or__?我尝试使用object.__or__and operator.__or__,但第一个给出 an AttributeError,第二个指的是按位|(或)运算符。

结果我有两个问题:

  1. 是否有一个类似的内置函数a or b
  2. 是否有这种空合并函数的内置实现?

两者的答案似乎是否定的,但这对我来说有点令人惊讶。

4

3 回答 3

8

它不完全是一个内置的,但您想要实现的目标可以通过以下方式轻松完成:

def null_coalesce(*a):
    return next(x for x in a if x)

它是懒惰的,所以它会像 一样短路a or b or c,但不像reduce.

您还可以使用以下方法使其特定于空:

def null_coalesce(*a):
    return next(x for x in a if x is not None)
于 2019-08-16T01:05:15.080 回答
5

是否有一个我可以使用的内置函数,它的作用类似于 a 或 b?

不。从这个答案中引用为什么:

orandand运算符不能表示为函数,因为它们的短路行为:

False and some_function()
True or some_function()

在这些情况下,some_function()永远不会调用。

or_(True, some_function())另一方面,假设的 必须调用some_function(),因为函数参数总是在调用函数之前进行评估。


是否有这种空合并函数的内置实现?

不,没有。但是,Python 文档页面itertools建议以下内容:

def first_true(iterable, default=False, pred=None):
    """Returns the first true value in the iterable.

    If no true value is found, returns *default*

    If *pred* is not None, returns the first item
    for which pred(item) is true.

    """
    # first_true([a,b,c], x) --> a or b or c or x
    # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
    return next(filter(pred, iterable), default)
于 2019-08-16T01:14:31.613 回答
1

Marco 说得对,没有内置的,而且 itertools 有一个配方。您也pip install boltons可以使用该boltons.iterutils.first()实用程序,如果您想要短路,这是完美的。

from boltons.iterutils import first

c = first([a, b])

中还有一些其他相关且方便的缩减工具iterutils,例如one().

我已经做了足够多的上述工作,实际上我最终想要一个更高级别的工具,它可以捕获 Python 数据结构中的整个交互(包括ab引用),产生glom及其Coalesce功能。

from glom import glom, Coalesce

target = {'b': 1}
spec = Coalesce('a', 'b')

c = glom(target, spec)
# c = 1

(完全披露,如上所述,我维护glomand boltons,这是个好消息,因为如果你发现错误,你可以给我找错误。)

于 2019-08-16T04:07:35.337 回答