The examples in the article recommend doing the right things, but I think the initial discussion of the LBYL vs EAFP discussion could be better.<p>The article says basically "LBYL is bad", but this isn't a good description of what the author does in the later examples. Following "EAFP" without exception is also really bad.<p>The simple policy is that you should use "LBYL" when you're dealing with local state that can't change out from under you, especially when it's just properties of your local variables, but you need to use "EAFP" for anything that deals with remote state. Function calls can go either way, depending.<p>Blanket advice against LBYL leads people to use try/except blocks to express basic conditionals. If you want to ask something about your local variables, just ask it in a conditional --- don't make the reader infer "ah, these are the situations which will raise the error, and therefore we'll go into this block if the values are this way". If you want to do something when a key is missing from a dictionary, don't write:<p><pre><code> try:
value = table[key]
except KeyError:
return default_value
</code></pre>
Just write:<p><pre><code> if key not in table:
return default_value
value = table[key]
</code></pre>
(If you really need to avoid two lookups for efficiency, you would do something like value = table.get(key, MISSING_VALUE) and then check 'if value is missing_value'. But this optimisation will seldom be necessary.)<p>The example the author gives about interacting with the file system is a good example of where indeed you really should use EAFP. The file system is remote state that your function does not own. Similarly if you're doing database operations, calling a remote API...lots of things.<p>There's various middle ground when you're calling functions. Often you don't want to worry about whether that function is going to be interacting with remote state, and you want to treat it totally as a black box, so you just use EAFP. But if the function documents really clear pre-conditions of your variables you can just go ahead and check, it's better to do that.
One thing that bothers me in my day-to-day Python work is that often libraries don’t document the errors that can be thrown by their functions. As the language lacks a “throws” statement, I found myself digging through library code on multiple occasions.
How do people approach this?
You can do nearly everything using Python errors. One thing that bothers me a bit, is the amount of text needed to catch them and bubble them up. Depending on the programming style traditional exceptions may also not be adequately re<p>For this Rust style error handling can be interesting, eg using poltergeist (<a href="https://github.com/alexandermalyga/poltergeist">https://github.com/alexandermalyga/poltergeist</a>) or result (<a href="https://pypi.org/project/result/" rel="nofollow">https://pypi.org/project/result/</a>).
Can someone explain the last bit:<p><pre><code> print(f"Unexpected error: {error}")
sys.exit(1)
</code></pre>
How is that any different than just letting the exception throw all the way out?<p>Is all this doing is making sure the exit code is 1 instead of some other non-zero value?<p>I'm not seeing how this is any better than just letting the program hard-crash.<p>(I am asking in earnest. I'm getting back into Python and wanting to know what's generally preferred)
It still has exceptions- but exceptions are normal. Errors are normal.
How would one do : <a href="https://fsharpforfunandprofit.com/rop/" rel="nofollow">https://fsharpforfunandprofit.com/rop/</a> in python?