目前我正在做这个:
try:
something = next(iterator)
# ...
except StopIteration:
# ...
但我想要一个可以放在简单的if
语句中的表达式。有没有内置的东西可以使这段代码看起来不那么笨拙?我只需要检查第一个项目。
目前我正在做这个:
try:
something = next(iterator)
# ...
except StopIteration:
# ...
但我想要一个可以放在简单的if
语句中的表达式。有没有内置的东西可以使这段代码看起来不那么笨拙?我只需要检查第一个项目。
if any(True for _ in iterator):
print('iterator had at least one element')
if all(False for _ in iterator):
print('iterator was empty')
any((x > 100 for x in xrange(10000000)))
,然后运行 any((x > 10000000 for x in xrange(100000000)))
-- 第二个应该花费更长的时间。 - chbrownsum(1 for _ in itertools.islice(iterator, max_len)) >= max_len
- Dave Butlerall(False for _ in iterator)
来检查迭代器是否为空。(all返回True如果迭代器为空,否则它会在看到第一个False元素时停止) - KGardevoirif list(iterator) == []
或者 if not any(iterator)
来检查它是否为空,或者使用 if any(iterator)
来检查它是否包含某些内容。 - Breaknext()
:sentinel = object()
if next(iterator, sentinel) is sentinel:
print('iterator was empty')
你还可以使用任何你“知道”(基于应用程序考虑)迭代器不可能产生的值作为哨兵值。
if not next(iterator, None):
就足够了,因为我确定 None 不会是其中的一项。感谢您指引我正确的方向! - wasabigeeknot
对于任何假值对象都会返回 True,例如空列表、False 和零。is not None
更安全,而且在我看来更清晰明了。 - Kyuuhachi这并不是真正的清晰简洁,但它展示了一种无损封装的方式:
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
这并不是非常符合 Python 编程风格,对于特定的情况,可能会有更好(但不太通用)的解决方案,例如next函数。
first = next(iter, None)
if first:
# Do something
这不是通用的,因为在许多可迭代对象中,None 可能是一个有效的元素。
next()
。 - Bastien LéonardNone
可能是一个完全合适的哨兵值,例如在 @BastienLéonard 的原始用例中,检查 SQL 查询是否有有效结果。 - Ken Williams最好的方法是使用来自more_itertools
的peekable
。
from more_itertools import peekable
iterator = peekable(iterator)
if iterator:
# Iterator is non-empty.
else:
# Iterator is empty.
注意,如果您保留了对旧迭代器的引用,则该迭代器将被推进。从那时起,您必须使用新的可窥探迭代器。 peekable
希望是唯一修改旧迭代器的代码。
more_itertools
不是Python标准库的一部分。 - tejasvi88您可以使用:
if zip([None], iterator):
# ...
else:
# ...
但是对于代码读者来说有点不够清晰易懂
关于:
In [1]: i=iter([])
In [2]: bool(next(i,False))
Out[2]: False
In [3]: i=iter([1])
In [4]: bool(next(i,False))
Out[4]: True
class NotSet: pass
,然后检查 if next(i, NotSet) is NotSet: print("Iterator is empty")
。 - Elijas Dapšauskas这是一个过度封装的迭代器,通常允许检查是否有下一个项目(通过转换为布尔值)。当然,非常低效。
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]
LookaheadIterator
(您不能将其与从标准库返回的迭代器一起使用),但即使如此,它似乎也符合OP的用例。 - not-just-yeti__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)).
- andrewrkdef it(): ... yield 1 ... yield 2 ... yield 3 ... i = it() i.length_hint Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'generator' object has no attribute 'length_hint'
# 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 (i.e. from the iterator)
else :
pass # Iterator was empty, thus list is empty.