Came across this gem today:
def reciprocal(n):
try:
n = 1 / n
except ZeroDivisionError:
print("Division failed")
n = None
else:
print("Everything went fine")
finally:
print("It's time to say goodbye")
return n
print(reciprocal(2))
print(reciprocal(0))
This made is tidier, but can't the content of the else block go into the try block and the finally block outside the try statement entirely - as below:
def reciprocal(n):
try:
n = 1 / n
print("Everything went fine")
except ZeroDivisionError:
print("Division failed")
n = None
print("It's time to say goodbye")
return n
Do they else and finally blocks serve a better purpose then then a "cleaner" statement?
Although this will work in this case and in general case - for the else
part (I will come to back later) there are cases where you definitely will need the finally
block and your code will be better using else
.
the else
part - generally the try
block should have as little code as possible, i.e. the code that can cause he error you handle in the except
part. Again, in this simple example it doesn't matter, but in more complex code it will make huge difference.
the finally
- there are cases, that even if you hit error and normal execution flow is interrupted you want to make sure certain tear-down/clean up code is executed, e.g. you may want write something to disk or close connection to a database, etc. That is where finally comes in play - you know that it will be executed even in case of error.
In the second snippet you never call reciprical.
Add that and you're fine
def reciprocal(n):
try:
n = 1 / n
print("Everything went fine")
except ZeroDivisionError:
print("Division failed")
n = None
print("It's time to say goodbye")
return n
print(reciprocal(2))
print(reciprocal(0))
Output:
Everything went fine
It's time to say goodbye
0.5
Division failed
It's time to say goodbye
None
Buran, sorry I posted at same time
(Jan-12-2021, 04:01 PM)Larz60+ Wrote: [ -> ]Buran, sorry I posted at same time
@
Larz60+, really don't know what you apologize for... :-)
Is having code in the "else" block any better than code in the "try" block? Is it because doing so places a harder focus on what code is expected to raise an exception?
try:
dangerous code
innocuous code
except:
handler code
#vs
try:
dangerous code
except:
handler code
else:
innocuous code
The upper example has the benefit of keeping the code together instead of splitting into little pieces. The bottom example has the benefit of pointing out what code is handled by the exception.
Does finally predate context managers? I can see using finally to close a file or do some other cleanup that is not done by other tools. I can see that it eliminates the need for duplicate code in the except and else blocks, but did it have a more important role?
You label the code "innocuous", but it's hard to guarantee that. In the first case if the innocuous code does raise an exception, it might (incorrectly) be caught by the exception handlers. Putting it in else guarantees that any exceptions it does raise are not caught locally.