On Sat, Feb 22, 2014 at 01:15:13PM +1300, Greg Ewing wrote:
Eli Bendersky wrote:
For instance, it is sometime non-trivial to know which exceptions some function may throw. When you write a try...raise statement, you think hard about covering all the bases. In an expression you're unlikely to,
Speak for yourself. I don't think I would put any less thought into which exception I caught with an except expression as I would for an except statement.
+1 With the possibly exception of messing about in the interactive interpreter, "catch as much as possible" is an anti-pattern. If you're not trying to catch as little as possible, you're doing it wrong.
In fact, an except expression may even make it easier to catch exceptions in an appropriately targeted way. For example, a pattern frequently encountered is:
result = computation(int(arg))
and you want to guard against arg not being a well-formed int. It's tempting to do this:
try: result = computation(int(arg)) except ValueError: abort("Invalid int")
But that's bad, because the try clause encompasses too much. Doing it properly requires splitting up the expression:
try: i = int(arg) except: abort("Invalid int") else: result = computation(i)
With an except expression, it could be written:
result = computation(int(arg) except ValueError: abort("Invalid int"))
Nice example! Except I'd lay the code out a bit better to emphasise which part is being guarded: result = computation( int(arg) except ValueError: abort("Invalid int") ) Actually, not quite so nice as I first thought, since you're relying on the side-effects of abort() rather than returning a value. But apart from that quibble, the ability to guard *small* subcalculations without needing a visually heavy try...block is a good use-case. -- Steven