try-else without except or finally

Hi Ideas, I frequently find myself in the following situations: 1) I wish to do something if no exception is thrown, for instance: try: logger.debug('Fiber starting: %s', self) try: self._result = self._routine() finally: logger.debug('Fiber finished: %s', self) except: raise else: raise FiberExit(self) finally: self._finished.set() unregister_fiber(self) Here it's sufficient that that if an exception is already present, I don't need to raise another. The except clause is clearly pointless. 2) I'm experimenting with catching various exceptions and remove the last except clause. I need to put a finally: pass; to avoid having to restructure all my code, since this is currently the only way to maintain the try-except-else-finally statement without catching dummy exceptions. I propose that the except clause be optional. Cheers, Matt

Omitting the except clause would make the code more obscure. 'else' means the second of two alternatives. Omitting the first alternative altogether obfuscates the code and makes it look as if the first alternative is the try block, i.e. it suggests if anything that the code following 'else:' is executed when there is an exception rather than when there isn't. -1 from me Rob Cliffe On 10/11/2011 08:10, Matt Joiner wrote:

On Thu, 2011-11-10 at 19:10 +1100, Matt Joiner wrote:
How is this...
different from this... try: logger.debug('Fiber starting: %s', self) try: self._result = self._routine() finally: logger.debug('Fiber finished: %s', self) raise FiberExit(self) finally: self._finished.set() unregister_fiber(self) That should do exactly what you want, shouldn't it? -- Dennis Kaarsemaker Senior Unix System Administrator Amsterdam, The Netherlands dennis.kaarsemaker@booking.com http://www.booking.com tel external +3120715 3409 tel internal (7207)3409

Yuval Greenfield wrote:
"Try...else..." doesn't make any sense without the except jn my eyes. The "else" has to conjugate something.
We already have while...else and for...else blocks in Python. The principle is the same: while condition(): ... else: # Run the else block unless we exit the while block with a break. ... try: ... else: # Run the else block unless we exit the try block with an exception. ... finally: ... This currently doesn't work without a pointless "except: raise" clause to satisfy the compiler. I try to avoid writing pointless code. -- Steven

Rob Cliffe wrote:
Look, I love the Zen as much as the next guy, but sometimes they get used as thought-terminating cliches. Catching an exception only to unconditionally raise it again unchanged is a waste of everybody's time: don't catch exceptions you have no intention of dealing with. Python has allowed try...finally without an except clause since version 1.5, if not earlier. Virtually every line of Python code may implicitly raise an exception. Despite the Zen, we don't go around writing try: n = len(x) except: raise just to satisfy the urge to make it explicit that any exception that occurs will be propagated. We don't need an explicit reminder that any exceptions will be propagated because, absent an except clause to explicitly silence it, that's what exceptions do: they propagate. Errors should never pass silently. Unless explicitly silenced. (see, I can quote the Zen too). -- Steven

Bear in mind new and inexperienced users, or perhaps someone who doesn't know Python at all but is trying to figure out what a Python program does. try: ... else: ... is not at all intuitive. If we want to allow that syntax, it would be better if 'else' were replaced by something more meaningful like 'ifnoexception'. Maybe someone can think of something meaningful but more concise. On 10/11/2011 14:24, Steven D'Aprano wrote:

On 10 November 2011 14:31, Rob Cliffe <rob.cliffe@btinternet.com> wrote:
"noexcept". However, I think "else" is fine. It's similar to how it's used in loops. We have: - if / else - for / break / else - while / break / else - try / except / else It makes sense to me. Also note that "else" is allowed after loops even if they have no "break". So why not allow "else" after a try without an except? -- Arnaud

Perhaps because an else: in this context, without being subordinate to anything, would be irrelevant, equivalent to 'pass' or, more exactly, 'if True:'. Else is always subordinate to some conditional clause$. The 'if' clause for try statements is the first except clause, not the try header: 'except x:' means something like 'if raised(x):' (since the corresponding try setup statement). The else clause is actually an elif clause: 'else:' means 'elif nothing_raised():'. To illustrate, the C equivalent of try: a = b/c except ZeroDivisionError: print('bah') else: print('hooray') would be (minus the punctuation that I have forgotten) something like errno = 0 /* setup error detection mechanism, just as try: does */ a = b/c if errno == EZERODIV /* or whatever it is */ printf('bah') elif errno == 0 /* ie, no error since setup */ printf('hooray') I suspect Python *could* have been defined to require 'except NOEXCEPTION:' instead of 'else:' by initializing an internal exception variable (equivalent to C's errno) with NOEXCEPTION. Howver, 'else:' is definitely nicer (just as normal 'else:' is equivalent to and nicer than 'elif True:'). $ A for loop is equivalent to a while loop with condition z"iterator (initially iter(iterable)) is not empty". Break and continue have the same meaning as in while loops. Any while loop, such as while c: x else: y is equivalent to an if statement with goto. In 'Python-with-label-and-goto' the above would be the same as label start_loop if c: x goto start_loop else: y So: in Python (as elsewhere), 'else' clauses always follow one or more headers that specify conditional execution and only trigger when the previous condition or conditions are false. Their use in various statement types is consistent and logically correct. -- Terry Jan Reedy

On 11/10/2011 5:21 PM, Matt Joiner wrote:
Your examples of else with loops are missing the extra behaviour on break?
I omitted 'break' as not relevant to the particular points I was aiming at. To add it in: while c: x if d: break else: y in PythonGTL could be label start_loop if c: x if d: goto after_loop goto start_loop else: y label after_loop
This is where the real value is in this usage.
Yes, 'break' is the main motivation for 'while...else'. Return and raise (explicit or otherwise) also break the loop. But since they raise stylistic preference issues, I won't go into them here. -- Terry Jan Reedy

Thanks for clarifying this. If anything, as mentioned earlier, the meaning of else isn't entirely obvious on the loops, nor is it obvious on try/except/else/finally clauses. The first time I encountered for/else I was dumbfounded, then I realised how handy it was. I wouldn't want to see these constructs removed. They remove the need for really nasty patterns, I'm sure this was discussed when they were added. On Fri, Nov 11, 2011 at 10:26 AM, Terry Reedy <tjreedy@udel.edu> wrote:

Guido van Rossum wrote:
Nobody's going to understand try...finally on first reading either, or for...else. And I can tell you, the first time I saw Python code, I had no idea how to translate "for x in something" into idioms I understood. The only for loops I had ever seen before then had been "for i = 1 to 100" Pascal/C style loops, and I was completely mystified. It seems somewhat bizarre to me that in another thread we are talking about about adding "cofunctions" to a language that already has threads, generators, coroutines and metaclasses, and then on the other hand we're worried that users won't be able to generalise try...else...finally from try...except...else...finally. However, Terry's explanation of Dennis' observation that any hypothetical try...else...finally block can be re-written as try...finally satisfies me. That's a good enough reason to keep the status quo. Downgrading my vote from +1 to +0. -- Steven

On Fri, Nov 11, 2011 at 9:43 AM, Steven D'Aprano <steve@pearwood.info> wrote:
A full -1 from me, for the reason already given: it's completely redundant. The "else:" clause on try statements exists specifically to cover the following situation: 1. You have code in a try block that may trigger associated exception handlers 2. One or more of those exception handlers may suppress the exception, allowing execution to resume after the try statement 3. You have some code that you want to run *only* if the try block doesn't throw an exception (i.e. if an exception is thrown and suppressed, you don't want to run this section of the code) If none of your exception handlers can suppress the exception and there's either no "finally:" close or it's OK if the additional code runs after the cleanup code, then "else:" is not really needed - you can just write the additional code after the whole try statement. If there are no exception handlers at all, then either don't use a try statement at all, or use a simple try-finally statement if you need some guaranteed cleanup. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Thu, Nov 10, 2011 at 7:41 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
4. You don't want exceptions is the else-block to be handled by any of the handlers. (Otherwise you could just put the else-block's code at the end of the try-block.)
-- --Guido van Rossum (python.org/~guido)

2011/11/14 alex23 <wuwei23@gmail.com>:
I see no value in adding another hardly understandable construct. Plus, in my mind try/else appears to be logically different than for/else (which I find very useful). -1 --- Giampaolo http://code.google.com/p/pyftpdlib/ http://code.google.com/p/psutil/

To be fair it's not a new construct, it's loosening the constraints on an existing one. else has the same use as in the for and while compound statements: It's executed if the first block completes "successfully". An exception being thrown in a try block, cancels execution of the "else" block, the same way as "break" in the for and while statements. I have a problem with the idea now in that: try: a else: b is the same as: try: a b else: pass and even: try: pass else: a b in every possible interpretation. This isn't possible with if, for, while, try/except, and try/finally compound statements, all of which alter the meaning in *some* way. So I maintain that the else block could be made allowable even without an except block, but it would be purely for convenience. I don't think it's worth it anymore. Cheers all for consideration. On Tue, Nov 15, 2011 at 1:25 AM, Giampaolo Rodolà <g.rodola@gmail.com> wrote:

On Mon, Nov 14, 2011 at 11:34 AM, Matt Joiner <anacrolix@gmail.com> wrote:
If you add finally, the else clause still maintains the same semantics in a try statement - only except statements modify the equivalence of else: try: a else: b finally: c is the same as: try: a b else: pass finally: c and try: pass else: a b finally: c What changes with the finally is that you cannot move the "b" statement out of the try completely. Without the finally clause, the following are the same: try: a else: b try: a b a b Similar behavior can be shown with for: else and while: else, if there is no break (I'm only showing a while statement below, however it converts exactly to a for statement): while a: b else: c is the same as: while a: b c so long as "b" does not include a break statement.
While it is redundant to allow else without except, I would agree that it should be allowed for the same reason that else is allowed on for and while without a break. The alternative would be to make the later illegal. Either seems reasonable, however the former maintains backwards compatibility, while the later breaks it.
Cheers all for consideration.

Chris Kaynor wrote:
if / else: if the 'if' condition is False, run the 'else' for / else: when the 'for' condition is False, run the 'else' while / else: when the 'while' condition is False, run the 'else' try /except / else: when the 'except' condition is False, run the 'else' try / else: when the 'try' condition is False, run the 'else' ?? To be consistent, the 'else' in a try/else would basically be an 'except Exception' -- it completely reverses the meaning of the 'else' in a try/except/else block. ~Ethan~

While it is redundant to allow else without except, I would agree that
yeah that nails it.
it should be allowed for the same reason that else is allowed on for> and while without a break. The alternative would be to make the later
that's a really good point, i hadn't considered this. similar things also occur when you "drop" out of some construct because you can predict the control flow. for example when certain blocks are guaranteed to throw exceptions, it becomes unnecessary to put alternative behaviour in an "else" block. try: a except: b raise c In the above, c does not get put in an else because it's redundant. The same applies here: if a: raise b c
illegal. Either seems reasonable, however the former maintains> backwards compatibility, while the later breaks it.
Yes for clarification you're saying: while a: b else: c Is redundant if b does not break. I think this puts the idea of else without except into the "why not?" camp for me. On Tue, Nov 15, 2011 at 7:04 AM, Chris Kaynor <ckaynor@zindagigames.com> wrote:

On 11/15/11, Chris Kaynor <ckaynor@zindagigames.com> wrote:
This change is *not going to happen*. Guido said drop it. Every core developer in the conversation said drop it. Please let the thread die already. The fact that 'else:' is allowed on loops without a break statement (despite such a construct being pointless) is just a way to simplify the language compilation process. While it obviously could be detected and prevented if we really wanted to (since we basically do that to allow 'yield' to alter the meaning of a function definition), reaching inside a suite to detect that kind of thing is a pain and simply not worth the hassle in this specific case. If it really bothers you, propose a patch to pyflakes (etc) that issues a warning for this kind of error (assuming they don't detect it already). In no way, shape or form does the fact we allow a particular redundant construct because detecting it is a pain to implement justify relaxing the parsing rules to allow an equally redundant construct that all compliant Python implementations *already* reject (and is much easier to detect in the first place, since the required precursor is a peer suite rather than a statement embedded inside such a suite). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On 11/14/2011 3:04 PM, Chris Kaynor wrote:
While it is redundant to allow else without except,
It is as redundant as allowing an 'else' without 'if', which is also not allowed. If fact, the exactly meaning of 'else' depends on what it is subordinate to -- 'if', 'while', 'for', or 'except'. So a bare 'else' would be ambiguous as to exact meaning, though the effect of 'pass' would be the same. The construct analogous to if...elif...else is except...except...else. After the first 'except', 'except' is an abbreviation for 'else-except', just as 'elif' is an abbreviation for 'else-if'. Try-else is *not* analogous to if-else. 'Try' is not a conditional. The next line *always* executes (successfully or not). 'Try' only means 'prepare a context for special treatment of exceptions'. One special treatment is to execute code only if there is an exception (after it is caught). The other is to execute code even if there is an exception.
I would agree that it should be allowed for the same reason that else is allowed on for and while without a break.
One is also allowed to write dubious code in numerous other ways: if <some condition that can never be true>: body if <some condition that must always be true>: body while <condition>: break; body while <condition>: body; break a=1; a=2 ... So what? The fact that a language spec, especially one limited to a context-free LL(1) grammar, allows one to write dead or irrelevant code in several ways is *not* a reason to add another, especially one that is logically incoherent and *always* useless, not just sometimes. The CPython parser and compiler are written to run reasonably fast. Third-party code checkers raise warnings for things they can catch with more extended analysis. Anyway, there is no analogy between 'try' and 'while' or 'for'. Both of the latter are 'if' statements augmented with a hidden goto to produce looping. The 'else' is subordinate to the 'if' part. Both can be terminated early by 'break', which is only allowed in loops. None of this has anything to do with 'try'.
The alternative would be to make the later illegal.
Try writing a Python-legal grammar that does that;-). -- Terry Jan Reedy

"Explicit is better than implicit." does not apply here at all. It's already known that an uncaught exception will not be caught and the rule was not applied there. except: raise is as redundant as: for stuff in things: do_the_things() else: pass On Fri, Nov 11, 2011 at 12:35 AM, Rob Cliffe <rob.cliffe@btinternet.com> wrote:

On Thu, Nov 10, 2011 at 3:28 PM, Steven D'Aprano <steve@pearwood.info>wrote:
I'd rename or remove for/else and while/else from the language. Guido has said "we probably should not do more of these". http://mail.python.org/pipermail/python-ideas/2009-October/006083.html Though these constructs are technically useful, even experts who read the documentation misunderstand or misuse them. People who are new to the language will be even worse. --Yuval

On 11/10/2011 8:28 AM, Steven D'Aprano wrote:
As Dennis Kaarsemaker already pointed out in his response to the OP, the 'else:' is not needed and this is the same (unless we are missing something) as try: ... ... In other words, *every* statement in a try block after the first is preceded by an implicit 'run this unless we already exited with an exception'. -- Terry Jan Reedy

On 10 November 2011 19:55, Terry Reedy <tjreedy@udel.edu> wrote:
Ah! I noted the post by Dennis Kaarsemaker pointing out that the original code could be rewritten without needing the dummy except or the else, but hadn't spotted that the argument generalised to *all* uses of an else without an except. Paul.

On 11/10/2011 02:28 PM, Steven D'Aprano wrote:
To me this would intuitively read as: Do the try block if you can, else (if you can't) do the else block. And you can't if an exception is raised. This is exactly the opposite of the intended meaning. The except is needed because the else refers to it. Without the except the else would refer to the try and one would expect behaviour as with an "except:" block. Also when ever would you need an else block without an except block? Just append it to the try block and you get the same behaviour. As for the not immediately intuitive meaning of the finally block: Yes, maybe "ensure" would have been better. But it's to late for that to change. -1 from me -panzi

Omitting the except clause would make the code more obscure. 'else' means the second of two alternatives. Omitting the first alternative altogether obfuscates the code and makes it look as if the first alternative is the try block, i.e. it suggests if anything that the code following 'else:' is executed when there is an exception rather than when there isn't. -1 from me Rob Cliffe On 10/11/2011 08:10, Matt Joiner wrote:

On Thu, 2011-11-10 at 19:10 +1100, Matt Joiner wrote:
How is this...
different from this... try: logger.debug('Fiber starting: %s', self) try: self._result = self._routine() finally: logger.debug('Fiber finished: %s', self) raise FiberExit(self) finally: self._finished.set() unregister_fiber(self) That should do exactly what you want, shouldn't it? -- Dennis Kaarsemaker Senior Unix System Administrator Amsterdam, The Netherlands dennis.kaarsemaker@booking.com http://www.booking.com tel external +3120715 3409 tel internal (7207)3409

Yuval Greenfield wrote:
"Try...else..." doesn't make any sense without the except jn my eyes. The "else" has to conjugate something.
We already have while...else and for...else blocks in Python. The principle is the same: while condition(): ... else: # Run the else block unless we exit the while block with a break. ... try: ... else: # Run the else block unless we exit the try block with an exception. ... finally: ... This currently doesn't work without a pointless "except: raise" clause to satisfy the compiler. I try to avoid writing pointless code. -- Steven

Rob Cliffe wrote:
Look, I love the Zen as much as the next guy, but sometimes they get used as thought-terminating cliches. Catching an exception only to unconditionally raise it again unchanged is a waste of everybody's time: don't catch exceptions you have no intention of dealing with. Python has allowed try...finally without an except clause since version 1.5, if not earlier. Virtually every line of Python code may implicitly raise an exception. Despite the Zen, we don't go around writing try: n = len(x) except: raise just to satisfy the urge to make it explicit that any exception that occurs will be propagated. We don't need an explicit reminder that any exceptions will be propagated because, absent an except clause to explicitly silence it, that's what exceptions do: they propagate. Errors should never pass silently. Unless explicitly silenced. (see, I can quote the Zen too). -- Steven

Bear in mind new and inexperienced users, or perhaps someone who doesn't know Python at all but is trying to figure out what a Python program does. try: ... else: ... is not at all intuitive. If we want to allow that syntax, it would be better if 'else' were replaced by something more meaningful like 'ifnoexception'. Maybe someone can think of something meaningful but more concise. On 10/11/2011 14:24, Steven D'Aprano wrote:

On 10 November 2011 14:31, Rob Cliffe <rob.cliffe@btinternet.com> wrote:
"noexcept". However, I think "else" is fine. It's similar to how it's used in loops. We have: - if / else - for / break / else - while / break / else - try / except / else It makes sense to me. Also note that "else" is allowed after loops even if they have no "break". So why not allow "else" after a try without an except? -- Arnaud

Perhaps because an else: in this context, without being subordinate to anything, would be irrelevant, equivalent to 'pass' or, more exactly, 'if True:'. Else is always subordinate to some conditional clause$. The 'if' clause for try statements is the first except clause, not the try header: 'except x:' means something like 'if raised(x):' (since the corresponding try setup statement). The else clause is actually an elif clause: 'else:' means 'elif nothing_raised():'. To illustrate, the C equivalent of try: a = b/c except ZeroDivisionError: print('bah') else: print('hooray') would be (minus the punctuation that I have forgotten) something like errno = 0 /* setup error detection mechanism, just as try: does */ a = b/c if errno == EZERODIV /* or whatever it is */ printf('bah') elif errno == 0 /* ie, no error since setup */ printf('hooray') I suspect Python *could* have been defined to require 'except NOEXCEPTION:' instead of 'else:' by initializing an internal exception variable (equivalent to C's errno) with NOEXCEPTION. Howver, 'else:' is definitely nicer (just as normal 'else:' is equivalent to and nicer than 'elif True:'). $ A for loop is equivalent to a while loop with condition z"iterator (initially iter(iterable)) is not empty". Break and continue have the same meaning as in while loops. Any while loop, such as while c: x else: y is equivalent to an if statement with goto. In 'Python-with-label-and-goto' the above would be the same as label start_loop if c: x goto start_loop else: y So: in Python (as elsewhere), 'else' clauses always follow one or more headers that specify conditional execution and only trigger when the previous condition or conditions are false. Their use in various statement types is consistent and logically correct. -- Terry Jan Reedy

On 11/10/2011 5:21 PM, Matt Joiner wrote:
Your examples of else with loops are missing the extra behaviour on break?
I omitted 'break' as not relevant to the particular points I was aiming at. To add it in: while c: x if d: break else: y in PythonGTL could be label start_loop if c: x if d: goto after_loop goto start_loop else: y label after_loop
This is where the real value is in this usage.
Yes, 'break' is the main motivation for 'while...else'. Return and raise (explicit or otherwise) also break the loop. But since they raise stylistic preference issues, I won't go into them here. -- Terry Jan Reedy

Thanks for clarifying this. If anything, as mentioned earlier, the meaning of else isn't entirely obvious on the loops, nor is it obvious on try/except/else/finally clauses. The first time I encountered for/else I was dumbfounded, then I realised how handy it was. I wouldn't want to see these constructs removed. They remove the need for really nasty patterns, I'm sure this was discussed when they were added. On Fri, Nov 11, 2011 at 10:26 AM, Terry Reedy <tjreedy@udel.edu> wrote:

Guido van Rossum wrote:
Nobody's going to understand try...finally on first reading either, or for...else. And I can tell you, the first time I saw Python code, I had no idea how to translate "for x in something" into idioms I understood. The only for loops I had ever seen before then had been "for i = 1 to 100" Pascal/C style loops, and I was completely mystified. It seems somewhat bizarre to me that in another thread we are talking about about adding "cofunctions" to a language that already has threads, generators, coroutines and metaclasses, and then on the other hand we're worried that users won't be able to generalise try...else...finally from try...except...else...finally. However, Terry's explanation of Dennis' observation that any hypothetical try...else...finally block can be re-written as try...finally satisfies me. That's a good enough reason to keep the status quo. Downgrading my vote from +1 to +0. -- Steven

On Fri, Nov 11, 2011 at 9:43 AM, Steven D'Aprano <steve@pearwood.info> wrote:
A full -1 from me, for the reason already given: it's completely redundant. The "else:" clause on try statements exists specifically to cover the following situation: 1. You have code in a try block that may trigger associated exception handlers 2. One or more of those exception handlers may suppress the exception, allowing execution to resume after the try statement 3. You have some code that you want to run *only* if the try block doesn't throw an exception (i.e. if an exception is thrown and suppressed, you don't want to run this section of the code) If none of your exception handlers can suppress the exception and there's either no "finally:" close or it's OK if the additional code runs after the cleanup code, then "else:" is not really needed - you can just write the additional code after the whole try statement. If there are no exception handlers at all, then either don't use a try statement at all, or use a simple try-finally statement if you need some guaranteed cleanup. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Thu, Nov 10, 2011 at 7:41 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
4. You don't want exceptions is the else-block to be handled by any of the handlers. (Otherwise you could just put the else-block's code at the end of the try-block.)
-- --Guido van Rossum (python.org/~guido)

2011/11/14 alex23 <wuwei23@gmail.com>:
I see no value in adding another hardly understandable construct. Plus, in my mind try/else appears to be logically different than for/else (which I find very useful). -1 --- Giampaolo http://code.google.com/p/pyftpdlib/ http://code.google.com/p/psutil/

To be fair it's not a new construct, it's loosening the constraints on an existing one. else has the same use as in the for and while compound statements: It's executed if the first block completes "successfully". An exception being thrown in a try block, cancels execution of the "else" block, the same way as "break" in the for and while statements. I have a problem with the idea now in that: try: a else: b is the same as: try: a b else: pass and even: try: pass else: a b in every possible interpretation. This isn't possible with if, for, while, try/except, and try/finally compound statements, all of which alter the meaning in *some* way. So I maintain that the else block could be made allowable even without an except block, but it would be purely for convenience. I don't think it's worth it anymore. Cheers all for consideration. On Tue, Nov 15, 2011 at 1:25 AM, Giampaolo Rodolà <g.rodola@gmail.com> wrote:

On Mon, Nov 14, 2011 at 11:34 AM, Matt Joiner <anacrolix@gmail.com> wrote:
If you add finally, the else clause still maintains the same semantics in a try statement - only except statements modify the equivalence of else: try: a else: b finally: c is the same as: try: a b else: pass finally: c and try: pass else: a b finally: c What changes with the finally is that you cannot move the "b" statement out of the try completely. Without the finally clause, the following are the same: try: a else: b try: a b a b Similar behavior can be shown with for: else and while: else, if there is no break (I'm only showing a while statement below, however it converts exactly to a for statement): while a: b else: c is the same as: while a: b c so long as "b" does not include a break statement.
While it is redundant to allow else without except, I would agree that it should be allowed for the same reason that else is allowed on for and while without a break. The alternative would be to make the later illegal. Either seems reasonable, however the former maintains backwards compatibility, while the later breaks it.
Cheers all for consideration.

Chris Kaynor wrote:
if / else: if the 'if' condition is False, run the 'else' for / else: when the 'for' condition is False, run the 'else' while / else: when the 'while' condition is False, run the 'else' try /except / else: when the 'except' condition is False, run the 'else' try / else: when the 'try' condition is False, run the 'else' ?? To be consistent, the 'else' in a try/else would basically be an 'except Exception' -- it completely reverses the meaning of the 'else' in a try/except/else block. ~Ethan~

While it is redundant to allow else without except, I would agree that
yeah that nails it.
it should be allowed for the same reason that else is allowed on for> and while without a break. The alternative would be to make the later
that's a really good point, i hadn't considered this. similar things also occur when you "drop" out of some construct because you can predict the control flow. for example when certain blocks are guaranteed to throw exceptions, it becomes unnecessary to put alternative behaviour in an "else" block. try: a except: b raise c In the above, c does not get put in an else because it's redundant. The same applies here: if a: raise b c
illegal. Either seems reasonable, however the former maintains> backwards compatibility, while the later breaks it.
Yes for clarification you're saying: while a: b else: c Is redundant if b does not break. I think this puts the idea of else without except into the "why not?" camp for me. On Tue, Nov 15, 2011 at 7:04 AM, Chris Kaynor <ckaynor@zindagigames.com> wrote:

On 11/15/11, Chris Kaynor <ckaynor@zindagigames.com> wrote:
This change is *not going to happen*. Guido said drop it. Every core developer in the conversation said drop it. Please let the thread die already. The fact that 'else:' is allowed on loops without a break statement (despite such a construct being pointless) is just a way to simplify the language compilation process. While it obviously could be detected and prevented if we really wanted to (since we basically do that to allow 'yield' to alter the meaning of a function definition), reaching inside a suite to detect that kind of thing is a pain and simply not worth the hassle in this specific case. If it really bothers you, propose a patch to pyflakes (etc) that issues a warning for this kind of error (assuming they don't detect it already). In no way, shape or form does the fact we allow a particular redundant construct because detecting it is a pain to implement justify relaxing the parsing rules to allow an equally redundant construct that all compliant Python implementations *already* reject (and is much easier to detect in the first place, since the required precursor is a peer suite rather than a statement embedded inside such a suite). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On 11/14/2011 3:04 PM, Chris Kaynor wrote:
While it is redundant to allow else without except,
It is as redundant as allowing an 'else' without 'if', which is also not allowed. If fact, the exactly meaning of 'else' depends on what it is subordinate to -- 'if', 'while', 'for', or 'except'. So a bare 'else' would be ambiguous as to exact meaning, though the effect of 'pass' would be the same. The construct analogous to if...elif...else is except...except...else. After the first 'except', 'except' is an abbreviation for 'else-except', just as 'elif' is an abbreviation for 'else-if'. Try-else is *not* analogous to if-else. 'Try' is not a conditional. The next line *always* executes (successfully or not). 'Try' only means 'prepare a context for special treatment of exceptions'. One special treatment is to execute code only if there is an exception (after it is caught). The other is to execute code even if there is an exception.
I would agree that it should be allowed for the same reason that else is allowed on for and while without a break.
One is also allowed to write dubious code in numerous other ways: if <some condition that can never be true>: body if <some condition that must always be true>: body while <condition>: break; body while <condition>: body; break a=1; a=2 ... So what? The fact that a language spec, especially one limited to a context-free LL(1) grammar, allows one to write dead or irrelevant code in several ways is *not* a reason to add another, especially one that is logically incoherent and *always* useless, not just sometimes. The CPython parser and compiler are written to run reasonably fast. Third-party code checkers raise warnings for things they can catch with more extended analysis. Anyway, there is no analogy between 'try' and 'while' or 'for'. Both of the latter are 'if' statements augmented with a hidden goto to produce looping. The 'else' is subordinate to the 'if' part. Both can be terminated early by 'break', which is only allowed in loops. None of this has anything to do with 'try'.
The alternative would be to make the later illegal.
Try writing a Python-legal grammar that does that;-). -- Terry Jan Reedy

"Explicit is better than implicit." does not apply here at all. It's already known that an uncaught exception will not be caught and the rule was not applied there. except: raise is as redundant as: for stuff in things: do_the_things() else: pass On Fri, Nov 11, 2011 at 12:35 AM, Rob Cliffe <rob.cliffe@btinternet.com> wrote:

On Thu, Nov 10, 2011 at 3:28 PM, Steven D'Aprano <steve@pearwood.info>wrote:
I'd rename or remove for/else and while/else from the language. Guido has said "we probably should not do more of these". http://mail.python.org/pipermail/python-ideas/2009-October/006083.html Though these constructs are technically useful, even experts who read the documentation misunderstand or misuse them. People who are new to the language will be even worse. --Yuval

On 11/10/2011 8:28 AM, Steven D'Aprano wrote:
As Dennis Kaarsemaker already pointed out in his response to the OP, the 'else:' is not needed and this is the same (unless we are missing something) as try: ... ... In other words, *every* statement in a try block after the first is preceded by an implicit 'run this unless we already exited with an exception'. -- Terry Jan Reedy

On 10 November 2011 19:55, Terry Reedy <tjreedy@udel.edu> wrote:
Ah! I noted the post by Dennis Kaarsemaker pointing out that the original code could be rewritten without needing the dummy except or the else, but hadn't spotted that the argument generalised to *all* uses of an else without an except. Paul.

On 11/10/2011 02:28 PM, Steven D'Aprano wrote:
To me this would intuitively read as: Do the try block if you can, else (if you can't) do the else block. And you can't if an exception is raised. This is exactly the opposite of the intended meaning. The except is needed because the else refers to it. Without the except the else would refer to the try and one would expect behaviour as with an "except:" block. Also when ever would you need an else block without an except block? Just append it to the try block and you get the same behaviour. As for the not immediately intuitive meaning of the finally block: Yes, maybe "ensure" would have been better. But it's to late for that to change. -1 from me -panzi
participants (18)
-
alex23
-
Antoine Pitrou
-
Arnaud Delobelle
-
Chris Kaynor
-
Dennis Kaarsemaker
-
Dj Gilcrease
-
Ethan Furman
-
Giampaolo Rodolà
-
Guido van Rossum
-
Mathias Panzenböck
-
Matt Joiner
-
MRAB
-
Nick Coghlan
-
Paul Moore
-
Rob Cliffe
-
Steven D'Aprano
-
Terry Reedy
-
Yuval Greenfield