给定一个列表,有没有一种方法可以获取第一个非 None 值?如果有,使用 Pythonic 的方式是什么?
例如,我有:
a = objA.addreses.country.code
b = objB.country.code
c = None
d = 'CA'
在这种情况下,如果 a 是 None,则我想得到 b。 如果 a 和 b 都为 None,则我想得到 d。
目前,我正在执行类似于 (((a or b) or c) or d)
的操作,还有其他方法吗?
next()
:>>> a = [None, None, None, 1, 2, 3, 4, 5]
>>> next(item for item in a if item is not None)
1
>>> a = [None, None, None]
>>> next((item for item in a if item is not None), 'All are Nones')
All are Nones
我认为这是处理少量值时最简单的方法:
firstVal = a or b or c or d
始终会返回第一个非“Falsey”值,在某些情况下有效(前提是您不希望返回任何可评估为false的值,正如@GrannyAching在下面所指出的那样)
first_true
是 Python 3 文档中 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)
您可以选择实现后者,或导入 more_itertools
库,该库随 itertools
配送了一些已经做好的“配方”和更多功能:
> pip install more_itertools
使用:
import more_itertools as mit
a = [None, None, None, 1, 2, 3, 4, 5]
mit.first_true(a, pred=lambda x: x is not None)
# 1
a = [None, None, None]
mit.first_true(a, default="All are None", pred=lambda x: x is not None)
# 'All are None'
为什么要使用谓词?
"第一个非 None
"的元素与"第一个 True
"的元素不同,例如[None,None,0]
,其中0
是第一个非 None
,但它不是第一个True
元素。谓词允许first_true
可用,确保迭代器中任何首次出现的非 None
的假值项目仍然被返回(例如0
,False
),而不是默认值。
a = [None, None, None, False]
mit.first_true(a, default="All are None", pred=lambda x: x is not None)
# 'False'
当列表中的项目计算成本高时,例如在
first_non_null = next((calculate(x) for x in my_list if calculate(x)), None)
# or, when receiving possibly None-values from a dictionary for each list item:
first_non_null = next((my_dict[x] for x in my_list if my_dict.get(x)), None)
那么你可能想要避免重复计算并简化为:
first_non_null = next(filter(bool, map(calculate, my_list)), None)
# or:
first_non_null = next(filter(bool, map(my_dict.get, my_list)), None)
由于使用了生成器表达式,计算只会对前面的项目执行,直到产生一个真值为止。
first_non_null = next(filter(bool, map(my_dict.get, my_list)), None)
- Azeezah M从以下内容进行改编(如果您愿意,可以将其压缩成一行):
values = (a, b, c, d)
not_None = (el for el in values if el is not None)
value = next(not_None, None)
这个函数返回第一个非 None
的值,或者返回 None
。
coalesce
。在Python中没有找到类似的功能,所以我自己编写了一个,使用了@alecxe的方法。请注意,保留HTML标签。def first_not_none(*values):
return next((v for v in values if v is not None), None)
在这种情况下确实非常有帮助:
attr = 'title'
document[attr] = first_not_none(cli_args.get(attr), document_item.get(attr),
defaults_item.get(attr), '')
try:
except StopIteration:
来处理仅包含 None 项的列表。但那是一个很好的答案。 - Germanonext((x for func in funcs if (x:= func(tree))), 'Default')
- bjonen