我确信有一种更简单的方法可以解决这个问题.
我正在调用一堆返回列表的方法.该列表可能为空.如果列表非空,我想返回第一个项目; 否则,我想要返回无.此代码有效:
my_list = get_list() if len(my_list) > 0: return my_list[0] return None
在我看来,应该有一个简单的单行成语,但对于我的生活,我无法想到它.在那儿?
编辑:
我在这里寻找单行表达式的原因并不是因为我喜欢简洁的代码,而是因为我必须编写很多像这样的代码:
x = get_first_list() if x: # do something with x[0] # inevitably forget the [0] part, and have a bug to fix y = get_second_list() if y: # do something with y[0] # inevitably forget the [0] part AGAIN, and have another bug to fix
我想要做的事情当然可以用一个函数来完成(也可能是):
def first_item(list_or_none): if list_or_none: return list_or_none[0] x = first_item(get_first_list()) if x: # do something with x y = first_item(get_second_list()) if y: # do something with y
我发布了这个问题,因为我常常对Python中的简单表达式能做什么感到惊讶,而且我认为如果有一个简单的表达式可以解决这个问题,编写函数是一件很愚蠢的事情.但看到这些答案,似乎功能就是简单的解决方案.
最好的方法是:
a = get_list() return a[0] if a else None
你也可以在一行中完成它,但程序员阅读起来要困难得多:
return (get_list()[:1] or [None])[0]
next(iter(your_list), None)
如果your_list
可以None
:
next(iter(your_list or []), None)
def get_first(iterable, default=None): if iterable: for item in iterable: return item return default
例:
x = get_first(get_first_list()) if x: ... y = get_first(get_second_list()) if y: ...
另一种选择是内联上述功能:
for x in get_first_list() or []: # process x break # process at most one item for y in get_second_list() or []: # process y break
为了避免break
你可以写:
for x in yield_first(get_first_list()): x # process x for y in yield_first(get_second_list()): y # process y
哪里:
def yield_first(iterable): for item in iterable or []: yield item return
(get_list() or [None])[0]
这应该工作.
BTW我没有使用变量list
,因为它会覆盖内置list()
函数.
编辑:我之前有一个稍微简单但错误的版本.
最蟒蛇惯用的方法是在迭代器上使用next(),因为列表是可迭代的.就像@JFSebastian在2011年12月13日的评论中提到的那样.
next(iter(the_list), None)
如果the_list
为空,则返回None .见next()Python 2.6+
或者如果你确定the_list
不是空的:
iter(the_list).next()
请参阅iterator.next()Python 2.2+
OP的解决方案几乎就在那里,只有一些东西可以让它更像Pythonic.
首先,没有必要得到列表的长度.Python中的空列表在if检查中评估为False.只是简单地说
if list:
另外,分配给与保留字重叠的变量是一个非常糟糕的想法."list"是Python中的保留字.
所以让我们改变它
some_list = get_list() if some_list:
非常重要的一点是,许多解决方案都缺少的是默认情况下所有Python函数/方法都返回None.请尝试以下方法.
def does_nothing(): pass foo = does_nothing() print foo
除非您需要返回None以提前终止函数,否则不必显式返回None.非常简洁,只要它存在就返回第一个条目.
some_list = get_list() if some_list: return list[0]
最后,也许这是隐含的,但只是为了明确(因为显式优于隐式),你不应该让你的函数从另一个函数中获取列表; 只是将其作为参数传递.所以,最终结果将是
def get_first_item(some_list): if some_list: return list[0] my_list = get_list() first_item = get_first_item(my_list)
就像我说的那样,OP几乎就在那里,只需要几点触动即可获得你想要的Python风格.
如果你发现自己试图从列表理解中挑选第一个(或无),你可以切换到生成器来执行它:
next((x for x in blah if cond), None)
Pro:如果blah不可索引,则有效Con:这是不熟悉的语法.虽然在ipython中进行黑客攻击并过滤内容时非常有用.