Python的成语返回的第一个项目或无
-
21-08-2019 - |
题
我敢肯定有这样做的,这只是不会发生在我的一个简单的方法。
我打电话了一堆返回列表的方法。该列表可能为空。如果列表非空,我想返回的第一个项目;否则,我想回到无。此代码的工作:
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可以做惊讶,我认为写一个函数是一个愚蠢的事情,如果有一个简单的表达可以做的伎俩。但是,在看到这些问题的答案,这似乎是一个功能的是的简单的解决方案。
解决方案
的Python 2.6 +
next(iter(your_list), None)
如果your_list
可以None
:
next(iter(your_list or []), None)
Python 2.4中
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
其他提示
,最好的方法是这样的:
a = get_list()
return a[0] if a else None
您也可以做到这一点的一条线,但它是非常困难的程序员阅读:
return (get_list()[:1] or [None])[0]
(get_list() or [None])[0]
这应该工作。
顺便说一句我没有使用可变list
,因为这将覆盖内置list()
功能。
编辑:我有一个稍微简单,但错误的版本早一点
最蟒惯用的方法是用下一个()上的迭代,因为列表是迭代。就像什么@ J.F.Sebastian摆在评论12月13为2011
next(iter(the_list), None)
这将返回无如果the_list
是空的。请参阅下()的Python 2.6+
或者如果你肯定知道the_list
不是空的:
iter(the_list).next()
看到 iterator.next()的Python 2.2+
在OP的解决方案几乎没有,目前只有几件事情,使之更加符合Python。
有关一个,有没有必要让列表的长度。在Python空列表评估为False在if检查。只需简单地说
if list:
此外,它是分配给该与保留字重叠变量非常坏主意。 “列表”是在Python保留字。
因此,让我们改变对
some_list = get_list()
if some_list:
这是一个很多解决方案在这里错过一个非常重要的一点是,所有的Python函数/方法默认返回None。尝试以下以下。
def does_nothing():
pass
foo = does_nothing()
print foo
除非你需要返回无提前终止的功能,这是没有必要明确地返回无。相当简洁,只返回的第一个条目,则应该存在。
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)
专家:工作,如果嗒嗒是不是可转位缺点:它是陌生的语法。而尽管在IPython的黑客周围和过滤材料是有用的。
for item in get_list():
return item
老实说,我不认为这是一个更好的成语:你是明确和简洁 - 不需要什么“更好”。也许吧,但是这的确是一个风格问题,你可以用if len(list) > 0:
改变if list:
- 一个空列表将永远评估为False
在一个相关的说明,Python是不会的Perl(没有双关语意!),你没有得到最酷的代码可能。结果 事实上,我在Python看到最坏代码,也非常凉爽和:-)完全难以维护。
对了,最让我在这里看到不考虑当列表[0]的值为False(如空字符串,或零)的解决方案 - 在这种情况下,他们都返回None,而不是正确的元素
<强>的Python成语返回第一项或无吗
最Python化的方法是什么最upvoted答案证明,这是第一件事就是来我的心,当我读的问题。以下是如何,如果可能的空列表传递给函数的使用,第一:
def get_first(l):
return l[0] if l else None
和如果所述列表是从一个get_list
函数返回:
l = get_list()
return l[0] if l else None
其他方式证明这里做到这一点,以解释
for
当我开始试图想巧妙的方法来做到这一点,这是我想到的第二件事情:
for item in get_list():
return item
此假定该函数在这里结束,如果None
返回一个空列表隐含返回get_list
。下面的显式代码是完全等效的:
for item in get_list():
return item
return None
if some_list
下面还建议(I校正不正确的变量名),它也使用了隐式None
。这将是优选的上述内容,因为它使用逻辑检查而不是可能不会发生迭代的。这应该是比较容易理解立即发生了什么。但是,如果我们正在编写可读性和可维护性,我们也应该在末尾添加明确return None
:
some_list = get_list()
if some_list:
return some_list[0]
切片or [None]
并选择第零索引
这一个也是最先进的表决的答案:
return (get_list()[:1] or [None])[0]
切片是不必要的,并且在内存中创建一个额外的一个项目列表。下面列出的是具有更好的性能。为了解释,or
返回第二元件如果第一是False
在布尔上下文,因此,如果get_list
返回一个空列表,包含在括号内的表达式将返回的列表,包括“无”,这将随后由0
索引访问:
return (get_list() or [None])[0]
下一个使用的事实,并且如果第一是True
在布尔上下文返回第二项,并且由于它引用my_list两次,这是不大于三元表达更好(上和技术上不是一个衬垫):
my_list = get_list()
return (my_list and my_list[0]) or None
next
然后,我们有以下巧妙地利用内置的next
和iter
return next(iter(get_list()), None)
要解释,iter
返回一个.next
方法的迭代器。 (在Python 3. .__next__
)然后,将内置next
调用.next
方法,并且如果该迭代器被耗尽,则返回我们给出的默认,None
。
冗余三元表达式(a if b else c
)和盘旋回
下面的提议,但逆将是优选的,因为逻辑通常较好在正而不是负的理解。由于get_list
被调用两次,除非结果以某种方式memoized,这将表现不佳:
return None if not get_list() else get_list()[0]
更好的逆:
return get_list()[0] if get_list() else None
更好的是,使用一个本地变量,以便get_list
仅调用一次,并且您有推荐的Python化溶液首先讨论:
l = get_list()
return l[0] if l else None
关于成语,有一个 itertools配方的称为nth
。
从itertools配方:
def nth(iterable, n, default=None):
"Returns the nth item or a default value"
return next(islice(iterable, n, None), default)
如果你想单行,可以考虑安装一个实现这个配方给你一个库,例如 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一般比例为任何可迭代,不仅为列表。
出于好奇,我跑的两个解的定时。它使用一个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.
try:
return a[0]
except IndexError:
return None
def head(iterable):
try:
return iter(iterable).next()
except StopIteration:
return None
print head(xrange(42, 1000) # 42
print head([]) # None
BTW:我返工你的一般程序流程弄成这个样子:
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))
(避免重复尽可能)
这样如何:
(my_list and my_list[0]) or None
注意:这应该工作的优良对象的列表,但它可能在每下面的评论数或字符串列表的情况下返回不正确的答案
。您可以使用提取方法。换句话说提取代码到一个方法,该方法你然后调用。
我不会试图压缩它更多,一个衬垫似乎难度比冗长的版本阅读。如果你使用的提取方法,它是一个内衬;)
使用和-或特技:
a = get_list()
return a and a[0] or None
和什么有关:next(iter(get_list()), None)
?
可能不是这里的一个最快的,但是标准的,简洁的(从Python 2.6中开始)。
也许不是最快的解决方案,但是没有人提到此选项:
dict(enumerate(get_list())).get(0)
如果get_list()
可以返回None
你可以使用:
dict(enumerate(get_list() or [])).get(0)
优点:
- 酮线
-you只是调用get_list()
一次
- 易于理解
我的用例,只是为了设置局部变量的值。
个人我发现try和除了式清洁器来读取
items = [10, 20]
try: first_item = items[0]
except IndexError: first_item = None
print first_item
比切片的列表。
items = [10, 20]
first_item = (items[:1] or [None, ])[0]
print first_item
if mylist != []:
print(mylist[0])
else:
print(None)
几个人都建议做这样的事情:
list = get_list()
return list and list[0] or None
这在很多情况下工作,但如果列表[0]不等于0,假,或一个空字符串它只会工作。如果列表[0]为0,False或空字符串,则该方法会错误地返回无。
我创建了这个错误在我自己的代码太多次!
不是蟒相当于惯用到C风格三元运营商
cond and true_expr or false_expr
即。
list = get_list()
return list and list[0] or None