我调用了一堆返回列表的方法。列表可能是空的。如果列表非空,我想返回第一项;否则,我想返回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
但是,在我看来,应该有一个简单的一行习语来做这件事。是吗?
当前回答
坦率地说,我认为没有更好的成语了:your is clear and short -不需要什么“更好的”。也许吧,但这真的是一个品味的问题,你可以改变if len(list) > 0:与if list: -一个空列表将永远求值为False。
在相关的说明中,Python不是Perl(没有双关的意思!),您不必获得尽可能最酷的代码。 实际上,我在Python中见过的最糟糕的代码,也是非常酷的:-),而且完全无法维护。
顺便说一下,我在这里看到的大多数解决方案都不考虑list[0]计算为False(例如空字符串或零)-在这种情况下,它们都返回None而不是正确的元素。
其他回答
如果你发现自己试图从列表理解中提取第一件事(或None),你可以切换到生成器来这样做:
next((x for x in blah if cond), None)
正方:如果blah是不可索引的,它是有效的,反面:它是不熟悉的语法。不过,当在ipython中破解和过滤东西时,它很有用。
def head(iterable):
try:
return iter(iterable).next()
except StopIteration:
return None
print head(xrange(42, 1000) # 42
print head([]) # None
顺便说一句:我会把你的一般程序流程重做成这样:
lists = [
["first", "list"],
["second", "list"],
["third", "list"]
]
def do_something(element):
if not element:
return
else:
# do something
pass
for li in lists:
do_something(head(li))
(尽可能避免重复)
(get_list() or [None])[0]
这应该有用。
顺便说一句,我没有使用变量列表,因为那会覆盖内置列表()函数。
编辑:我之前有一个稍微简单,但错误的版本。
你可以使用提取方法。换句话说,将代码提取到一个方法中,然后调用该方法。
我不会试图进一步压缩它,一行代码似乎比冗长的版本更难阅读。如果你使用提取方法,它是一行;)
出于好奇,我对其中两个解决方案进行了计时。使用return语句提前结束for循环的解决方案在我的机器上使用Python 2.5.1的代价略高,我怀疑这与设置可迭代对象有关。
import random
import timeit
def index_first_item(some_list):
if some_list:
return some_list[0]
def return_first_item(some_list):
for item in some_list:
return item
empty_lists = []
for i in range(10000):
empty_lists.append([])
assert empty_lists[0] is not empty_lists[1]
full_lists = []
for i in range(10000):
full_lists.append(list([random.random() for i in range(10)]))
mixed_lists = empty_lists[:50000] + full_lists[:50000]
random.shuffle(mixed_lists)
if __name__ == '__main__':
ENV = 'import firstitem'
test_data = ('empty_lists', 'full_lists', 'mixed_lists')
funcs = ('index_first_item', 'return_first_item')
for data in test_data:
print "%s:" % data
for func in funcs:
t = timeit.Timer('firstitem.%s(firstitem.%s)' % (
func, data), ENV)
times = t.repeat()
avg_time = sum(times) / len(times)
print " %s:" % func
for time in times:
print " %f seconds" % time
print " %f seconds avg." % avg_time
以下是我得到的时间:
empty_lists: index_first_item: 0.748353 seconds 0.741086 seconds 0.741191 seconds 0.743543 seconds avg. return_first_item: 0.785511 seconds 0.822178 seconds 0.782846 seconds 0.796845 seconds avg. full_lists: index_first_item: 0.762618 seconds 0.788040 seconds 0.786849 seconds 0.779169 seconds avg. return_first_item: 0.802735 seconds 0.878706 seconds 0.808781 seconds 0.830074 seconds avg. mixed_lists: index_first_item: 0.791129 seconds 0.743526 seconds 0.744441 seconds 0.759699 seconds avg. return_first_item: 0.784801 seconds 0.785146 seconds 0.840193 seconds 0.803380 seconds avg.