在搜索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}})但是异常只会发生一次,即只要迭代器耗尽就会发生。 在这种情况下,异常处理是更好的解决方案吗?
答案 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/else
和try/catch
都有其优点和缺点。
try/catch
主要用于异常为罕见事件的情况(例如,代码几乎在所有情况下都会成功)。try/catch
非常低效答案 2 :(得分:1)
当您在文档中看到等效的python代码时,此类代码的目标很容易理解。 if
很容易理解,而try/except
是更高级别的构造。
从功能上讲,没有区别。在性能方面,可能存在一个小的,但可能微不足道的差异。
就实际编码而言,不同的人会以不同的方式思考,因此请使用对您更有意义的方法。 LBYL和EAFP实际上有所作为的时间是一个竞争条件可以存在 - 而且这里没有这样的条件。