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
不是False
、None
、空或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:
or
和and
运算符不能表示为函数,因为它们的 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 数据结构中捕获整个交互(包括 a
和 b
引用),从而产生 glom
及其Coalesce
功能。
from glom import glom, Coalesce
target = 'b': 1
spec = Coalesce('a', 'b')
c = glom(target, spec)
# c = 1
(完全公开,如上所述,我维护glom
和boltons
,这是个好消息,因为如果您发现错误,you can bug me。)
【讨论】:
以上是关于Python中的多参数空合并和内置“或”函数的主要内容,如果未能解决你的问题,请参考以下文章