如何处理耗尽的迭代器?

时间:2015-07-30 08:44:16

标签: python python-3.x exception-handling generator

在搜索Python Documentation时,我发现了Pythons内置的{em>等效python实现 zip() function

而不是捕获 StopIteration异常,它表示迭代器没有生成其他项目作者使用if语句检查返回的默认值表单next()是否等于object()(“sentinel”)并停止生成器:

def zip(*iterables):
    # zip('ABCD', 'xy') --> Ax By
    sentinel = object()
    iterators = [iter(it) for it in iterables]
    while iterators:
        result = []
        for it in iterators:
            elem = next(it, sentinel)

            if elem is sentinel:
                return

            result.append(elem)
        yield tuple(result)

我现在想知道Python Docs使用的异常捕获或if语句之间是否存在之间的差异?

或者更好,正如@hiro protagonist所指出的那样: 使用try语句 考虑{{}有什么问题Python中的3}} EAFP

def zip(*iterables):
    # zip('ABCD', 'xy') --> Ax By
    iterators = [iter(it) for it in iterables]
    while iterators:
        result = []
        for it in iterators:

            try:
                elem = next(it)
            except StopIteration:
                return

            result.append(elem)
        yield tuple(result)

同样正如(Easier to ask for forgiveness than permission)提到“如果没有引发异常,那么try / except块非常有效。实际上,捕获异常非常昂贵。”({ {3}})但是异常只会发生一次,即只要迭代器耗尽就会发生。 在这种情况下,异常处理是更好的解决方案吗?

3 个答案:

答案 0 :(得分:9)

你的意思是与此相反吗?

def zip2(*iterables):
    # zip('ABCD', 'xy') --> Ax By
    iterators = [iter(it) for it in iterables]
    while iterators:
        result = []
        for it in iterators:
            try:
                elem = next(it)
            except StopIteration:
                return

            result.append(elem)
        yield tuple(result)

有趣的问题......我更喜欢这个替代版本 - 尤其是考虑EAFP(更容易要求宽恕而不是许可。)

即使try / except比if语句慢;这只发生一次 - 只要第一个迭代器耗尽。

值得注意的是,这不是python中的实际实现;只是与实际实现等效的实现。

更新根据评论:

请注意,PEP 479向生成器return建议,而不是StopIteration

答案 1 :(得分:5)

通常,在任何编程语言中,提高异常都被认为是一项昂贵的操作。有很多网站可以阅读为什么会这样,我不打算详细介绍它涉及的内容。

来自Python Docs

  

如果没有引发异常,try / except块非常有效。实际上捕获异常是很昂贵的。

根据具体情况,使用if/elsetry/catch都有其优点和缺点。

  • 例如,try/catch主要用于异常为罕见事件的情况(例如,代码几乎在所有情况下都会成功)。
  • 在您的示例中,您知道每次调用循环都会抛出异常,这使得使用try/catch非常低效

答案 2 :(得分:1)

当您在文档中看到等效的python代码时,此类代码的目标很容易理解。 if很容易理解,而try/except是更高级别的构造。

从功能上讲,没有区别。在性能方面,可能存在一个小的,但可能微不足道的差异。

就实际编码而言,不同的人会以不同的方式思考,因此请使用对您更有意义的方法。 LBYL和EAFP实际上有所作为的时间是一个竞争条件可以存在 - 而且这里没有这样的条件。