How to handle an exhausted iterator?
在搜索python文档时,我发现了在
不是捕获一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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文档使用的
或者更好,正如@hiro主人公指出的那样:
在python中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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) |
同样,正如Stoyan Dekov提到的,"如果没有引发异常,尝试/例外块是非常有效的。实际上捕获异常是昂贵的。"(有关详细信息,请参阅文档)
但异常只会发生一次,即在迭代器用完后立即发生。那么在这种情况下,异常处理是更好的解决方案吗?
你的意思是和这个相反?
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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建议发电机向
通常,在任何编程语言中,引发异常都被认为是一种昂贵的操作。有很多网站可以阅读这是为什么,我不打算详细讨论它涉及到什么。
来自python文档。
A try/except block is extremely efficient if no exceptions are raised. Actually catching an exception is expensive.
使用
- 例如,
try/catch 主要用于异常很少发生的情况(例如,代码在几乎所有情况下都会成功)。 - 在您的示例中,您知道循环在每次调用时都会抛出一个异常,这使得使用
try/catch 非常低效。
当您在文档中看到等效的python代码时,这样的代码的目标是易于理解。
功能上没有区别。从性能上讲,可能有一个小的,但可能微不足道的差异。
就实际的编码过程而言,不同的人用不同的方式思考,所以使用对您来说更合理的方法。当lbyl和eafp真正起作用的时候,就是一个竞争条件可以存在的时候——这里没有这样的条件。