Python 使用异常进行控制流被认为是不好的吗?
好吧,我过去曾多次看到过这种说法,但最近是 我的try.. except
问题在这里。所以,我很好奇为什么会出现这种情况,在 Python 中,因为生成器使用异常来指示数据的结尾。
如果这对每个使用 Python 的人来说都如此糟糕,为什么该语言将其包含在被认为是基本控制结构中?对于那些想要阅读相关 PEP 的人,请参阅 PEP 255:简单生成器。
Alright, I've seen this claimed multiple times in the past, but most recently with my try..except
question here. So, I'm curious why this is the case, in Python because generators use exceptions to indicate the end of the data.
If this is so bad for everyone using Python, why does the language include it in what are considered fundamental control structures? For those who want to read the relevant PEP, see PEP 255:Simple Generators.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
因为结束生成器不是一个常见事件(我知道它总是会发生,但只发生一次)。抛出异常被认为是昂贵的。如果一个事件在 99% 的情况下成功,1% 的情况失败,那么使用 try/ except 比检查是否可以访问该数据要快得多(请求原谅比请求许可更容易)。
人们对它也存在偏见,因为这样使用的 try/ except 块可能非常难以理解。流程控制可能很难遵循,而 if/else 则更简单。 try/except 意味着您必须跟踪它调用的函数内的 try 和 内的语句的流程控制(因为它们可能会抛出异常并且可能会向上传播。if/else 可以仅在评估语句时进行分支。
有时使用 try/ except 是正确的,有时使用 if/else 更有意义。考虑一下:与第一个
。
相比 如果 key 不存在于 a 内部并且只会稍微快一些(几乎不明显)如果它存在,则第二个会更快,但如果它不存在,则速度会慢得多,否则,第一个有效。编辑
:只需添加一点关于 Python try/ except 的内容,这对解决可读性问题有很大帮助。
。
现在,
do stuff to the file
中的任何内容都可能会抛出异常 异常,我们会捕获它。出于这个原因,尝试在 try 中保留尽可能少的代码。 Python 有一个可选的 try 子句,只有当 try 运行完成且没有遇到异常时,该子句才会运行。在这种情况下,您不会遇到任何可读性问题,因为 try 中只有一条语句;它是一个Python标准库函数调用,你只捕获特定的异常。
Because ending the generator is not a common event (I know it will always happen, but it only happens once). Throwing the exception is considered expensive. If an event is going to succeed 99% of the time and fail 1%, using try/except can be much faster than checking if it's okay to access that data (it's easier to ask forgiveness than permission).
There's also a bias against it since try/except blocks used like that can be very difficult to understand. The flow control can be difficult to follow, while an if/else are more straightforward. The try/except means you have to track the flow control of the statements inside the try and inside of the functions it calls (as they may throw the exception and it may propagate upwards. An if/else can only branch at the point when the statement is evaluated.
There are times when using try/except is correct and times when if/else make more sense. There are also performance costs associated with each of them. Consider:
vs.
The first will be faster if key does not exist inside of a and will only be slightly (almost unnoticeable) slower if it does exist. The second will be faster if the key does exist, but will be much slower if it doesn't exist. If key almost always exists, you go with the second. Otherwise, the first works better.
EDIT: Just a little thing to add about Python try/except that helps greatly with one of the readability problems.
Consider reading from a file.
Now anything in the
do stuff to the file
can throw an exception and we'll catch it. Commonly, you try to keep as little code as possible in the try for this reason. Python has an optionalelse
clause for the try that will only be run if the try ran to completion without hitting an exception.In this case, you would not have any of the readability problems since only one statement is in the try; it is a python standard library function call and you're catching only specific exceptions.
由于异常是在堆栈中向上引发的,因此它们适用于您希望使用其他代码的代码能够捕获异常的某些情况。例如,考虑一下您想要创建一个更“手动”地使用另一个迭代器的一部分的迭代器的情况,拥有一个可以从堆栈高层捕获并插入您自己的逻辑的异常是很有价值的。
Because exceptions are raised up the stack, they are appropriate for some cases where you want code that uses other code to be able to catch the exception. For example, consider the case where you want to create an iterator that uses part of another iterator more "manually", it's valuable to have an exception you can catch from higher up the stack and insert your own logic.
始终使用 try 块进行流量控制可能会生成如下代码:
撇开性能问题不谈,这不是很优雅。因此,有时使用
try
是完全合适的,但并非适用于所有情况。Using
try
blocks for flow control all the time could produce code like this:Performance concerns aside, this is not very elegant. So, sometimes it's perfectly appropriate to use
try
, but not for everything.