检查迭代器是否至少生成一个元素的单行代码?

146 投票
8 回答
87498 浏览
提问于 2025-04-16 00:24

目前我正在这样做:

try:
    something = next(iterator)
    # ...
except StopIteration:
    # ...

但是我想要一个可以放在简单的 if 语句里的表达式。有内置的东西可以让这段代码看起来不那么笨重吗?我只需要检查第一个项目。

8 个回答

28

这其实并不是更简洁的写法,但它展示了一种可以无损地把代码封装成函数的方法:

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可能是一个有效的元素。

65

将一个哨兵值作为next()的默认值传入:

sentinel = object()

if next(iterator, sentinel) is sentinel:
    print('iterator was empty')

你还可以使用任何你“知道”的值(根据应用的具体情况)作为哨兵值,这个值是迭代器绝对不会返回的。

183
if any(True for _ in iterator):
    print('iterator had at least one element')
if all(False for _ in iterator):
    print('iterator was empty')

请注意,如果这个可迭代对象至少有一个元素,这个操作会消耗掉第一个元素。

撰写回答