有没有一种简单的方法来测试生成器是否没有项目,比如peek,hasNext,isEmpty,这些是什么?
建议:
def peek(iterable): try: first = next(iterable) except StopIteration: return None return first, itertools.chain([first], iterable)
用法:
res = peek(mysequence) if res is None: # sequence is empty. Do stuff. else: first, mysequence = res # Do something with first, maybe? # Then iterate over the sequence: for element in mysequence: # etc.
你问题的简单答案:不,没有简单的方法.有很多解决方法.
真的不应该有一个简单的方法,因为生成器是什么:一种输出一系列值而不将序列保存在内存中的方法.所以没有向后遍历.
你可以编写一个has_next函数,或者甚至可以将它作为一个带有花式装饰器的方法打到生成器上,如果你愿意的话.
一种简单的方法是使用next()的可选参数,如果生成器耗尽(或为空),则使用该参数.例如:
iterable = some_generator() _exhausted = object() if next(iterable, _exhausted) == _exhausted: print('generator is empty')
编辑:更正了mehtunguh评论中指出的问题.
next(generator, None) is not None
或者更换,None
但无论你知道什么价值都不在您的发电机中.
编辑:是的,这将跳过生成器中的1项.但是,我经常检查生成器是否为空以用于验证目的,然后不要真正使用它.或者我做的事情如下:
def foo(self): if next(self.my_generator(), None) is None: raise Exception("Not initiated") for x in self.my_generator(): ...
也就是说,如果您的生成器来自某个函数,则可以使用此函数generator()
.
最好的方法,恕我直言,将避免一个特殊的测试.大多数情况下,使用发电机是测试:
thing_generated = False # Nothing is lost here. if nothing is generated, # the for block is not executed. Often, that's the only check # you need to do. This can be done in the course of doing # the work you wanted to do anyway on the generated output. for thing in my_generator(): thing_generated = True do_work(thing)
如果这还不够好,您仍然可以执行明确的测试.此时,thing
将包含生成的最后一个值.如果没有生成任何内容,它将是未定义的 - 除非您已经定义了变量.你可以查看它的值thing
,但这有点不可靠.相反,只需在块中设置一个标志,然后检查它:
if not thing_generated: print "Avast, ye scurvy dog!"
我讨厌提供第二个解决方案,特别是我不会自己使用的解决方案,但是,如果你绝对不得不这样做而不使用生成器,就像在其他答案中一样:
def do_something_with_item(item): print item empty_marker = object() try: first_item = my_generator.next() except StopIteration: print 'The generator was empty' first_item = empty_marker if first_item is not empty_marker: do_something_with_item(first_item) for item in my_generator: do_something_with_item(item)
现在我真的不喜欢这个解决方案,因为我认为这不是生成器的使用方式.