我只是写了一些我想做的代码:
def foo(container)
return any((some_obj.attr <= 0 for some_obj in container))
Run Code Online (Sandbox Code Playgroud)
其中,foo将返回第一个some_obj地方some_obj.attr是零或更低.我想,另一种选择是
def foo(container):
return next((some_obj for some_obj in container if some_obj.attr <= 0), False)
Run Code Online (Sandbox Code Playgroud)
但这感觉非常hacky.
我最终写出来了,但我不喜欢它有多深入嵌套.
def foo(container):
for some_obj in container:
if some_obj.attr <= 0:
return some_obj
return False
Run Code Online (Sandbox Code Playgroud)
澄清container一下:在这种情况下,可能不超过6个对象(通常是2个对象),尽管一般情况更有用.我也试图优化阅读的简易性,而不是性能.
有没有比这更好的构造?
aba*_*ert 12
文档any解释它相当于:
def any(iterable):
for element in iterable:
if element:
return True
return False
Run Code Online (Sandbox Code Playgroud)
因此,如果代码与用于说明其any自身功能的代码具有完全相同的结构,我认为您的代码不会嵌套太深.
不过,我可能会将其包含在一个函数中:
def first(iterable, predicate):
for element in iterable:
if predicate(element):
return element
return False
Run Code Online (Sandbox Code Playgroud)
所以现在你可以这样做:
def foo(container):
return first(container, lambda obj: obj.attr <= 0)
Run Code Online (Sandbox Code Playgroud)
或者,或者,只需使用生成器表达式,并将其传递给双参数next,就像您已经在做的那样:
def foo(container):
return next((obj for obj in container if obj.attr <= 0), False)
Run Code Online (Sandbox Code Playgroud)
它具有相同的"深度",它只是全部水平而不是垂直.
或者,也许,拔出genexpr并命名它:
def foo(container):
nonpositives = (obj for obj in container if obj.attr <= 0)
return next(nonpositives, False)
Run Code Online (Sandbox Code Playgroud)
你会如何在他们之间做出选择?我认为如果谓词太复杂,不能读作lambda但不够复杂,值得抽象成一个外联函数,我会选择genexpr.否则,包装函数.但这真的是品味问题.
next(filter应该这样做,这是一个有趣的测试方式<= 0:
>>> next(filter((0).__ge__, [3,2,1,-1,-2]), False)
-1
Run Code Online (Sandbox Code Playgroud)
哈,甚至滔滔不绝:
>>> next(filter(0..__ge__, [3,2,1,-1,-2]), False)
-1
Run Code Online (Sandbox Code Playgroud)
或者,正如abarnert所指出的那样:
>>> next(filter(0 .__ge__, [3,2,1,-1,-2]), False)
-1
Run Code Online (Sandbox Code Playgroud)