循环遍历空迭代器不会引发异常

时间:2020-02-04 11:16:20

标签: python python-3.x for-loop

我使用的是Python 3.6.7。

我刚刚注意到,在空白列表上的for循环甚至不会循环一次。 经过一番思考,这对我来说很有意义。即大小为零(空)的对象上的循环返回零次迭代。

iterable = []
for element in iterable:
    pass
print(element)
>>> NameError: name 'element' is not defined

这意味着如果使用len(iterable) == 0,则不会在循环内执行测试。

iterable = []
for element in iterable:
    assert isinstance(element, int)
#nothing happens

那我该如何捕捉这种情况?

当由于iterable为空而导致循环不运行时,是否存在一种紧凑的内置方法来引发错误?

要适应这种特殊情况,需要手动进行:

  • 在循环之前测试iterator是否为空
  • 在循环之后测试元素是否已定义。都没有 方法对我来说似乎很优雅

我可能最终在每个for循环中都要进行此测试。

assert len(iterable) > 0
#loop

#loop
assert "element" in dir() #?

3 个答案:

答案 0 :(得分:2)

您可以使用Statements, and else Clauses on Loops

循环语句可以包含else子句;当循环通过穷尽迭代器终止时执行。

例如:

iterator = []
for element in iterator:
    print('This wont print..')
else:
    assert iterator

这将导致:

Traceback (most recent call last):
  File "<pyshell#2>", line 4, in <module>
    assert iterator
AssertionError

答案 1 :(得分:2)

如果由于列表为空而导致循环无法运行,为什么还要执行某些操作?这是完全正常的行为。如果您出于某种原因期望至少有一个项目(也许数组中没有项目可以衡量程序中的错误),请按照前面的建议检查是否len(iterator) == 0。这是一种完全有效的方法。

在这种情况下,当您检查变量等的值时,应该使用exepties的方式。断言更多是针对严重故障的硬编码信息,不应用于报告常见错误,因为它们不能处理。

答案 2 :(得分:1)

没有内置的方法可以直接检查空的迭代器。空迭代器通常不被视为例外。但是,您可以定义紧凑型助手来显式检查空的迭代器。


通常不可能预先检测空的迭代器。在某些情况下,您可以从迭代器的源中猜测它是否为空-例如,如果序列和映射的迭代器的父级为boolean false,则它们为空。但是,迭代器本身没有任何内容指示,除非进行迭代,否则实际上可能是“空”的。

唯一可靠的方法是检查迭代器在迭代时是否提供项目。 可以定义一个包装迭代器,如果迭代器根本不提供任何项目,则会引发错误。

def non_empty(iterable):
    """Helper to ensure that ``iterable`` is not empty during iteration"""
    iterator = iter(iterable)
    try:
        yield next(iterator)  # explicitly check first item
    except StopIteration:
        raise LookupError(f'{iterable} is empty') from None
    yield from iterator       # forward iteration of later items

这样的帮助程序可以包装在迭代器和迭代器中,并可以在for循环,显式iter迭代器和任何其他迭代方案中使用。

>>> iterable = []
>>> for element in non_empty(iterable):
...    assert isinstance(element, int)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in non_empty
LookupError: [] is empty