Python 中的多参数空合并和内置 "or" 函数

Multi-argument null coalesce and built-in "or" function in Python

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

c = a or b

如果 a 不是 FalseNone、空或 0,则将 c 设置为 a,否则 c 设置为 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 似乎不是最理想的 - 肯定有像 __or__ 这样的内置程序吧?我尝试使用 object.__or__ and operator.__or__,但第一个给出 AttributeError,第二个指的是按位 |(或)运算符。

因此我有两个问题:

  1. 有没有像a or b一样的内置函数?
  2. 是否有这样一个空合并函数的内置实现?

两者的答案似乎是否定的,但这让我有些惊讶。

它不完全是一个内置的,但你想要实现的可以很容易地完成:

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

它很懒,所以它会像a or b or c一样短路,但不像reduce

您还可以通过以下方式使其特定于 null:

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

Is there a built-in function which I can use which acts like a or b?

没有。引用自 this answer on why:

The or and and operators can't be expressed as functions because of their short-circuiting behavior:

False and some_function()
True or some_function()

in these cases, some_function() is never called.

A hypothetical or_(True, some_function()), on the other hand, would have to call some_function(), because function arguments are always evaluated before the function is called.


Is there a built-in implementation of such a null coalesce function?

不,没有。但是,the Python documentation page for 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)

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

from boltons.iterutils import first

c = first([a, b])

还有一些其他相关且方便的 reduction tools in iterutils,例如 one()

我已经做了足够多的上述工作,以至于我最终想要一个更高级别的工具,可以在 Python 数据结构,产生 glom and its Coalesce 功能。

from glom import glom, Coalesce

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

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

(完全公开,如上所述,我维护 glomboltons,这是个好消息,因为 you can bug me 如果你发现错误。)