好的,
在过去我已经见过很多次了,但是最近我的问题是这样的。所以,我很好奇为什么会出现这种情况,python中的因为生成器使用异常来指示数据的结束。
如果这对每个使用python的人来说都很糟糕,为什么python语言将其包含在被认为是基本控制结构的内容中呢?
因为结束生成器不是一个常见的事件(我知道它总是会发生,但它只发生一次)。抛出异常被认为代价高昂。如果一个事件99%的概率成功,1%的概率失败,使用try/except比检查是否可以访问数据要快得多(请求原谅比请求允许更容易)。
也有一个偏见,因为像这样使用try/except块可能很难理解。流控制可能很难遵循,而if/else则更直接。try/except意味着您必须跟踪它调用的函数中的try 和内的语句的流控制(因为它们可能抛出异常并向上传播)。if/else语句只能在对语句求值时进行分支。
有时使用try/except是正确的,有时使用if/else更有意义。每一种方法都有相关的性能成本。考虑:
a = <some dictionary>
if key in a:
print a[key]
与
a = <some dictionary>
try:
print a[key]
except KeyError:
pass
如果key不存在于a中,第一个会更快;如果key存在,它只会稍微慢一点(几乎不明显)。如果键存在,第二个会更快,但如果它不存在,则会慢得多。如果key几乎总是存在,就用第二个。否则,第一个更好。
编辑:关于Python try/只是一个小小的补充,除了它极大地帮助了可读性问题之一。
考虑从文件中读取。
f = None
try:
f = open(filename, 'r')
... do stuff to the file ...
except (IOError, OSError):
# I can never remember which one of these Python throws...
... handle exception ...
finally:
if f:
f.close()
现在do stuff to the file
中的任何东西都可以抛出异常,我们将捕获它。通常,出于这个原因,您会尝试在try中保留尽可能少的代码。Python有一个可选的else
子句,它只会在try运行到完成而没有遇到异常的情况下运行。
f = None
try:
f = open(filename, 'r')
except (IOError, OSError):
pass
else:
... do stuff to the file ...
finally:
if f:
f.close()
在这种情况下,你不会有任何可读性问题,因为只有一条语句在try;这是一个python标准库函数调用,你只捕获特定的异常。
因为异常是在堆栈中上升的,所以它们适用于一些情况,当您希望使用其他代码的代码能够捕获异常时。例如,如果你想创建一个迭代器,该迭代器更"手动"地使用另一个迭代器的一部分,那么有一个异常可以从堆栈的上层捕获并插入你自己的逻辑,这是很有价值的。
始终使用try
块进行流量控制可能产生如下代码:
try:
# stuff
try:
if userCondition:
raise NeedToDoSomethingElseException
try:
# stuff
except NeedToDoSomethingElseException:
# other stuff
except NeedToDoSomethingElseException:
# other stuff
except NeedToDoSomethingElseException:
# other stuff
撇开性能问题不谈,这不是很优雅。所以,有时使用try
是完全合适的,但不是所有的。