Rob*_*ney 241 python idioms python-2.4
我确信有一种更简单的方法可以解决这个问题.
我正在调用一堆返回列表的方法.该列表可能为空.如果列表非空,我想返回第一个项目; 否则,我想要返回无.此代码有效:
my_list = get_list()
if len(my_list) > 0: return my_list[0]
return None
Run Code Online (Sandbox Code Playgroud)
在我看来,应该有一个简单的单行成语,但对于我的生活,我无法想到它.在那儿?
编辑:
我在这里寻找单行表达式的原因并不是因为我喜欢简洁的代码,而是因为我必须编写很多像这样的代码:
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
Run Code Online (Sandbox Code Playgroud)
我想要做的事情当然可以用一个函数来完成(也可能是):
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
Run Code Online (Sandbox Code Playgroud)
我发布了这个问题,因为我常常对Python中的简单表达式能做什么感到惊讶,而且我认为如果有一个简单的表达式可以解决这个问题,编写函数是一件很愚蠢的事情.但看到这些答案,似乎功能就是简单的解决方案.
efo*_*nis 200
最好的方法是:
a = get_list()
return a[0] if a else None
Run Code Online (Sandbox Code Playgroud)
你也可以在一行中完成它,但程序员阅读起来要困难得多:
return (get_list()[:1] or [None])[0]
Run Code Online (Sandbox Code Playgroud)
jfs*_*jfs 171
next(iter(your_list), None)
Run Code Online (Sandbox Code Playgroud)
如果your_list可以None:
next(iter(your_list or []), None)
Run Code Online (Sandbox Code Playgroud)
def get_first(iterable, default=None):
if iterable:
for item in iterable:
return item
return default
Run Code Online (Sandbox Code Playgroud)
例:
x = get_first(get_first_list())
if x:
...
y = get_first(get_second_list())
if y:
...
Run Code Online (Sandbox Code Playgroud)
另一种选择是内联上述功能:
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
Run Code Online (Sandbox Code Playgroud)
为了避免break你可以写:
for x in yield_first(get_first_list()):
x # process x
for y in yield_first(get_second_list()):
y # process y
Run Code Online (Sandbox Code Playgroud)
哪里:
def yield_first(iterable):
for item in iterable or []:
yield item
return
Run Code Online (Sandbox Code Playgroud)
rec*_*ive 67
(get_list() or [None])[0]
Run Code Online (Sandbox Code Playgroud)
这应该工作.
BTW我没有使用变量list,因为它会覆盖内置list()函数.
编辑:我之前有一个稍微简单但错误的版本.
Dev*_*evy 31
最蟒蛇惯用的方法是在迭代器上使用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+
got*_*nes 10
OP的解决方案几乎就在那里,只有一些东西可以让它更像Pythonic.
首先,没有必要得到列表的长度.Python中的空列表在if检查中评估为False.只是简单地说
if list:
Run Code Online (Sandbox Code Playgroud)
另外,分配给与保留字重叠的变量是一个非常糟糕的想法."list"是Python中的保留字.
所以让我们改变它
some_list = get_list()
if some_list:
Run Code Online (Sandbox Code Playgroud)
非常重要的一点是,许多解决方案都缺少的是默认情况下所有Python函数/方法都返回None.请尝试以下方法.
def does_nothing():
pass
foo = does_nothing()
print foo
Run Code Online (Sandbox Code Playgroud)
除非您需要返回None以提前终止函数,否则不必显式返回None.非常简洁,只要它存在就返回第一个条目.
some_list = get_list()
if some_list:
return list[0]
Run Code Online (Sandbox Code Playgroud)
最后,也许这是隐含的,但只是为了明确(因为显式优于隐式),你不应该让你的函数从另一个函数中获取列表; 只是将其作为参数传递.所以,最终结果将是
def get_first_item(some_list):
if some_list:
return list[0]
my_list = get_list()
first_item = get_first_item(my_list)
Run Code Online (Sandbox Code Playgroud)
就像我说的那样,OP几乎就在那里,只需要几点触动即可获得你想要的Python风格.
Aid*_*ane 10
如果你发现自己试图从列表理解中挑选第一个(或无),你可以切换到生成器来执行它:
next((x for x in blah if cond), None)
Run Code Online (Sandbox Code Playgroud)
Pro:如果blah不可索引,则有效Con:这是不熟悉的语法.虽然在ipython中进行黑客攻击并过滤内容时非常有用.
关于习语,有一个itertools 配方,名为nth.
来自 itertools 食谱:
def nth(iterable, n, default=None):
"Returns the nth item or a default value"
return next(islice(iterable, n, None), default)
Run Code Online (Sandbox Code Playgroud)
如果您想要简单的话,请考虑安装一个为您实现此配方的库,例如more_itertools:
import more_itertools as mit
mit.nth([3, 2, 1], 0)
# 3
mit.nth([], 0) # default is `None`
# None
Run Code Online (Sandbox Code Playgroud)
另一种工具仅返回第一项,称为more_itertools.first。
mit.first([3, 2, 1])
# 3
mit.first([], default=None)
# None
Run Code Online (Sandbox Code Playgroud)
这些 itertool 一般适用于任何可迭代对象,而不仅仅是列表。
Python 习惯用法返回第一项还是无?
最 Pythonic 的方法是最受好评的答案所展示的,这是我阅读问题时首先想到的。下面是如何使用它,首先,如果可能的空列表被传递给一个函数:
def get_first(l):
return l[0] if l else None
Run Code Online (Sandbox Code Playgroud)
如果列表是从get_list函数返回的:
l = get_list()
return l[0] if l else None
Run Code Online (Sandbox Code Playgroud)
赋值表达式使用就地赋值运算符(非正式地称为海象运算符),:=Python 3.8 中的新功能允许我们就地进行检查和赋值,允许单行:
return l[0] if (l := get_list()) else None
Run Code Online (Sandbox Code Playgroud)
作为一名长期使用 Python 的用户,这感觉就像我们试图在一条线上做太多事情 - 我觉得做假设性相同的性能会更好:
if l := get_list():
return l[0]
return None
Run Code Online (Sandbox Code Playgroud)
支持这种表述的是 Tim Peter在 PEP 中提议对语言进行这种更改的文章。他没有提到第一个公式,但根据他喜欢的其他公式,我认为他不会介意。
for当我开始尝试想出聪明的方法来做到这一点时,这是我想到的第二件事:
for item in get_list():
return item
Run Code Online (Sandbox Code Playgroud)
这假定函数在这里结束,None如果get_list返回空列表则隐式返回。下面的显式代码完全等效:
for item in get_list():
return item
return None
Run Code Online (Sandbox Code Playgroud)
if some_list还提出了以下内容(我更正了不正确的变量名称),它也使用了隐式None. 这比上面的更可取,因为它使用逻辑检查而不是可能不会发生的迭代。这应该更容易立即理解正在发生的事情。但是如果我们是为了可读性和可维护性而编写的,我们还应该return None在末尾添加显式:
some_list = get_list()
if some_list:
return some_list[0]
Run Code Online (Sandbox Code Playgroud)
or [None]并选择第零个索引这也是投票最多的答案:
return (get_list()[:1] or [None])[0]
Run Code Online (Sandbox Code Playgroud)
切片是不必要的,它会在内存中创建一个额外的单项列表。以下应该更有效。为了解释一下,or如果第一个元素False在布尔上下文中,则get_list返回第二个元素,因此如果返回一个空列表,则括号中包含的表达式将返回一个带有“None”的列表,然后将通过0索引访问该列表:
return (get_list() or [None])[0]
Run Code Online (Sandbox Code Playgroud)
如果第一个True在布尔上下文中,则下一个使用 and 返回第二个项目的事实,并且由于它两次引用 my_list,它并不比三元表达式好(技术上不是单行):
my_list = get_list()
return (my_list and my_list[0]) or None
Run Code Online (Sandbox Code Playgroud)
next然后我们有以下巧妙地使用内置next和iter
return next(iter(get_list()), None)
Run Code Online (Sandbox Code Playgroud)
解释一下,iter返回一个带有.next方法的迭代器。(.__next__在 Python 3 中。)然后内置函数next调用该.next方法,如果迭代器耗尽,则返回我们给出的默认值None。
a if b else c) 和回圈提出了以下建议,但最好采用相反的方式,因为逻辑通常从正面而不是负面来更好地理解。由于get_list被调用两次,除非以某种方式记忆结果,否则这将表现不佳:
return None if not get_list() else get_list()[0]
Run Code Online (Sandbox Code Playgroud)
更好的逆:
return get_list()[0] if get_list() else None
Run Code Online (Sandbox Code Playgroud)
更好的是,使用局部变量以便get_list只调用一次,并且您首先讨论了推荐的 Pythonic 解决方案:
l = get_list()
return l[0] if l else None
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
273212 次 |
| 最近记录: |