我调用了一堆返回列表的方法。列表可能是空的。如果列表非空,我想返回第一项;否则,我想返回None。这段代码工作:
def main():
my_list = get_list()
if len(my_list) > 0:
return my_list[0]
return None
但是,在我看来,应该有一个简单的一行习语来做这件事。是吗?
我调用了一堆返回列表的方法。列表可能是空的。如果列表非空,我想返回第一项;否则,我想返回None。这段代码工作:
def main():
my_list = get_list()
if len(my_list) > 0:
return my_list[0]
return None
但是,在我看来,应该有一个简单的一行习语来做这件事。是吗?
当前回答
more_itertools借款。First_true代码产生一些可读的东西:
def first_true(iterable, default=None, pred=None):
return next(filter(pred, iterable), default)
def get_first_non_default(items_list, default=None):
return first_true(items_list, default, pred=lambda x: x!=default)
其他回答
如果你发现自己试图从列表理解中提取第一件事(或None),你可以切换到生成器来这样做:
next((x for x in blah if cond), None)
正方:如果blah是不可索引的,它是有效的,反面:它是不熟悉的语法。不过,当在ipython中破解和过滤东西时,它很有用。
下面的代码涵盖了使用lambda的几个场景:
l1 = [1,2,3]
l2 = []
l3 = None
first_elem = lambda x: x[0] if x else None
print(first_elem(l1))
print(first_elem(l2))
print(first_elem(l3))
不确定这是如何python化的,但在库中有第一个函数之前,我将其包含在源代码中:
first = lambda l, default=None: next(iter(l or []), default)
它只有一行(符合黑色),避免了依赖关系。
(get_list() or [None])[0]
这应该有用。
顺便说一句,我没有使用变量列表,因为那会覆盖内置列表()函数。
编辑:我之前有一个稍微简单,但错误的版本。
关于习语,有一个itertools食谱叫做nth。
来自itertools食谱:
def nth(iterable, n, default=None):
"Returns the nth item or a default value"
return next(islice(iterable, n, None), default)
如果你想要一行程序,可以考虑安装一个库来实现这个recipe,例如more_itertools:
import more_itertools as mit
mit.nth([3, 2, 1], 0)
# 3
mit.nth([], 0) # default is `None`
# None
还有另一个只返回第一项的工具,叫做more_itertools.first。
mit.first([3, 2, 1])
# 3
mit.first([], default=None)
# None
这些itertools一般适用于任何可迭代对象,而不仅仅适用于列表。