在Python生成器中使用… else
题
我非常喜欢Python的 for ... else语法 - 令人惊讶的是它的适用频率,以及它如何有效地简化代码。
但是,我还没有找到在生成器中使用它的好方法,例如:
def iterate(i):
for value in i:
yield value
else:
print 'i is empty'
在上面的例子中,我希望仅当 i
为空时才执行 print
语句。但是,由于 else
仅尊重 break
和 return
,因此无论 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()
总结一些早期的答案,可以这样解决:
def iterate(i):
empty = True
for value in i:
yield value
empty = False
if empty:
print "empty"
所以真的没有“其他”涉及的条款。
如您所知, for..else
仅检测 break
。所以它只适用于你寻找的东西,然后停止。
它不适用于您的目的,不是因为它是一个生成器,而是因为您想要处理所有元素而不停止(因为您想要全部产生它们,但这不是重点)。 / p>
所以生成器与否,你真的需要一个布尔值,就像Ber的解决方案一样。
如果不能以这种方式使用... 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
不隶属于 StackOverflow