单线程来检查一个迭代器是否至less产生一个元素?
目前我正在这样做:
try: something = iterator.next() # ... except StopIteration: # ...
但我想要一个expression式,我可以放在一个简单的if
语句中。 有什么内置的,这将使这个代码看起来不那么笨拙?
如果一个iterable是空的,则any()
返回False
,但如果不是,则它将会遍历所有的项目。 我只需要检查第一个项目。
有人问我在做什么。 我已经写了一个函数,执行一个SQL查询并产生结果。 有时当我调用这个函数时,我只想知道查询是否返回任何内容,并根据这个做出决定。
如果它是真的, any
不会超出第一个元素。 如果迭代器产生一些错误,你可以写any(True for _ in iterator)
。
在Python 2.6+中,如果名字sentinel
绑定到迭代器不可能产生的值,
if next(iterator, sentinel) is sentinel: print('iterator was empty')
如果您不知道迭代器可能会产生什么结果,请使用自己的定点(例如,在模块的顶部)
sentinel = object()
否则,您可以在标记angular色中使用您“知道”的任何值(基于应用程序考虑)迭代器不可能产生的值。
这并不是很干净,但它展示了一种无损地将其打包成函数的方法:
def has_elements(iter): from itertools import tee iter, any_check = tee(iter) try: any_check.next() return True, iter except StopIteration: return False, iter has_el, iter = has_elements(iter) if has_el: # not empty
这不是pythonic,对于特定的情况,可能有更好的(但不太一般的)解决scheme,就像下一个默认的那样。
first = next(iter, None) if first: # Do something
这不是一般的,因为在许多迭代中None都不是一个有效的元素。
您可以使用:
if zip([None], iterator): # ... else: # ...
但对代码阅读器来说这是有点不合理的
__length_hint__
估计 list(it)
的长度 – 它是私有方法,但是:
x = iter( (1, 2, 3) ) help(x.__length_hint__) 1 Help on built-in function __length_hint__: 2 3 __length_hint__(...) 4 Private method returning an estimate of len(list(it)).
这是一个过度的迭代器包装,通常允许检查是否有下一个项目(通过转换为布尔)。 当然相当低效。
class LookaheadIterator (): def __init__(self, iterator): self.__iterator = iterator try: self.__next = next (iterator) self.__have_next = True except StopIteration: self.__have_next = False def __iter__(self): return self def next (self): if self.__have_next: result = self.__next try: self.__next = next (self.__iterator) self.__have_next = True except StopIteration: self.__have_next = False return result else: raise StopIteration def __nonzero__(self): return self.__have_next x = LookaheadIterator (iter ([])) print bool (x) print list (x) x = LookaheadIterator (iter ([1, 2, 3])) print bool (x) print list (x)
输出:
False [] True [1, 2, 3]
有点晚了,但是…你可以把迭代器变成一个列表,然后使用该列表:
# Create a list of objects but runs out the iterator. l = [_ for _ in iterator] # If the list is not empty then the iterator had elements; else it was empty. if l : pass # Use the elements of the list (ie from the iterator) else : pass # Iterator was empty, thus list is empty.