Python中的多参数空合并和内置“或”函数

Posted

技术标签:

【中文标题】Python中的多参数空合并和内置“或”函数【英文标题】:Multi-argument null coalesce and built-in "or" function in Python 【发布时间】:2019-12-22 08:59:02 【问题描述】:

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__operator.__or__,但第一个给出了AttributeError,第二个指的是按位|(或)运算符。

因此我有两个问题:

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

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

【问题讨论】:

在 PEP 505 上提出了无合并、-aware、-safe 运算符,它具有延迟状态。 @alkasm 不,这是按位或运算符。 【参考方案1】:

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

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)

【讨论】:

null_coalesce([0,0,3]) == [0, 0, 3] 那里发生了什么? @wjandrea 它是星形参数,而不是单个参数。如果您只想返回 3,则应该将 0, 0, 3 传递给函数,而不是 [0, 0, 3] @alkasm 哦,哎呀【参考方案2】:

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

没有。引用this answer on why:

orand 运算符不能表示为函数,因为它们的 short-circuiting 行为:

False and some_function()
True or some_function()

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

另一方面,假设的or_(True, some_function()) 必须调用some_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)

【讨论】:

或者,operator.or_ @alkasm operator.__or__operator.or_ 用于按位或。那是另一回事。我注意到后迅速编辑了我的答案。 在这里面有一个谓词的能力真是太好了+1 糟糕!好电话!【参考方案3】:

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

from boltons.iterutils import first

c = first([a, b])

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

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

from glom import glom, Coalesce

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

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

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

【讨论】:

以上是关于Python中的多参数空合并和内置“或”函数的主要内容,如果未能解决你的问题,请参考以下文章

Python中的多线程如何正确运用?案例详解

Python中的多线程如何正确运用?案例详解

python内置函数都有哪些

具有haskell中的多参数函数的延迟过滤器

C#中的多线程问题,为啥带参数的方法不行,不带参数的可以?

没有参数/可迭代的函数的多处理池?