替换返回最后一个评估对象的`any`?

Ada*_*ith 11 python

我只是写了一些我想做的代码:

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.否则,包装函数.但这真的是品味问题.

  • 好吧,我真的希望有人会进来说"哦,你不知道你能做什么?或者*容器"? (2认同)

Ste*_*ann 5

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)