检测空序列的更好for循环语法?

11 投票
5 回答
2940 浏览
提问于 2025-04-16 09:11

有没有更好的方法来写下面的代码:

   row_counter = 0
   for item in iterable_sequence:
      # do stuff with the item

      counter += 1

   if not row_counter:
      # handle the empty-sequence-case

请注意,我不能使用 len(iterable_sequence),因为 1) 不是所有的序列都有已知的长度;2) 在某些情况下,调用 len() 可能会导致序列的项目被加载到内存中(比如 SQL 查询结果的情况)。

我之所以问这个,是因为我很好奇有没有更简洁、更符合习惯的写法。我想要的写法大概是这样的:

for item in sequence:
   #process item
*else*:
   #handle the empty sequence case

(假设这里的“else”只对空序列有效,虽然我知道实际上并不是这样)

5 个回答

2

J.F. Sebastian的第二个例子似乎是用while循环来解决问题的好方法。

NoItem = object()
myiter = (x for x in range(10))
item = next(myiter, NoItem)
if item is NoItem:
    ...
else:
    while item is not NoItem:
        print item
        item = next(myiter, NoItem)

虽然不是最简洁的写法,但客观上来说是最清晰的……有点复杂,对吧?

3

这可能是用到 itertools.tee 的时候了。你在验证的时候“触发”了序列,但之后你会有一个未被修改的序列副本:

from itertools import tee
check, sequence = tee(sequence, 2)

try:
   check.next():
except StopIteration:
   #empty sequence
for item in sequence:
     #do stuff

值得注意的是,tee 在这里做了“正确”的事情:当你执行 check.next() 时,它只会加载序列的第一个元素,而这个第一个元素会在 sequence 中保持可用。剩下的元素只会在 for 循环中被取出。
或者说得简单点:如果你不能使用 len,你就无法检查序列是否有布尔值为 True,原因是一样的。

所以,你的方式看起来简单得多——另一种方法是在 for 语句之前删除“item”这个名字,然后在循环结束后检查它是否存在:

del item
for item in sequence:
    # do stuff
try:
    item
except NameError:
     # sequence is empty.

但你的代码应该被使用,因为它比这个更清晰。

8
for item in iterable:
    break
else:
    # handle the empty-sequence-case here

或者

item = next(iterator, sentinel)
if item is sentinel:
   # handle the empty-sequence-case here   

在每种情况下,如果有一个项目,它会被消耗掉。


在评论中提到的empty_adapter()的实现示例:

def empty_adaptor(iterable, sentinel=object()):
    it = iter(iterable)
    item = next(it, sentinel)
    if item is sentinel:
       return None # empty
    else:
       def gen():
           yield item
           for i in it:
               yield i
       return gen()

你可以这样使用它:

it = empty_adaptor(some_iter)
if it is not None: 
   for i in it:
       # handle items
else:
   # handle empty case

为一个通用情况引入一个空序列的特殊情况似乎是不太对劲的。应该有更好的解决方案来处理特定领域的问题。

撰写回答