繁体   English   中英

在Python生成器中使用for…else

[英]Using for…else in Python generators

我是Python的... else语法的忠实拥护者 -令人惊讶的是它的应用频率以及简化代码的有效性。

但是,我还没有找到在生成器中使用它的好方法,例如:

def iterate(i):
    for value in i:
        yield value
    else:
        print 'i is empty'

在上面的示例中,我希望仅在i为空时才执行print语句。 然而,随着else只有方面breakreturn ,它总是执行的长度无关, i

如果无法以这种方式for...else ,那么最好的方法是什么,以便仅在不产生任何结果时才执行print语句?

您正在破坏生成器的定义,该定义应在迭代完成时引发StopIteration异常(生成器函数中的return语句会自动处理该异常)

所以:

def iterate(i):
    for value in i:
        yield value
    return

最好让调用代码处理空迭代器的情况:

count = 0
for value in iterate(range([])):
    print value
    count += 1
else:
    if count == 0:
        print "list was empty"

可能是做上述事情的一种更清洁的方法,但是应该可以正常工作,并且不属于下面常见的任何“像列表一样处理迭代器”陷阱。

有两种方法可以做到这一点。 您总是可以直接使用Iterator

def iterate(i):
    try:
        i_iter = iter(i)
        next = i_iter.next()
    except StopIteration:
        print 'i is empty'
        return

    while True:
        yield next
        next = i_iter.next()

但是,如果您对参数i期望的了解更多,则可以更加简洁:

def iterate(i):
    if i:  # or if len(i) == 0
        for next in i:
            yield next
    else:
        print 'i is empty'
        raise StopIteration()

如您所述, for..else仅检测到break 因此,它仅在您寻找某物然后停止时才适用。

它不是适用于您的目的,不是因为它是生成器,而是因为您想处理所有元素而不停止 (因为您想产生所有元素 ,但这不是重点)。

不管是否生成器,就像Ber的解决方案中一样,您确实需要布尔值。

总结一些较早的答案,可以这样解决:

def iterate(i):
    empty = True
    for value in i:
        yield value
        empty = False

    if empty:
        print "empty"

因此,实际上没有涉及“ else”子句。

如果无法以这种方式用于... else,那么最好的方法是什么,以便仅在不产生任何结果时才执行print语句?

我能想到的最大值:


>>> empty = True
>>> for i in [1,2]:
...     empty = False
... if empty:
...     print 'empty'
...
>>>
>>>
>>> empty = True
>>> for i in []:
...     empty = False
... if empty:
...    print 'empty'
...
empty
>>>

简单的if-else呢?

def iterate(i):
    if len(i) == 0: print 'i is empty'
    else:
        for value in i:
            yield value

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM