Rejection by Guido:https://mail.python.org/pipermail/python-dev/2017-September/149232.html
This PEP proposes enhancing thebreak andcontinue statementswith an optional boolean expression that controls whether or notthey execute. This allows the flow of control in loops to beexpressed more clearly and compactly.
Quoting from the rejectedPEP 315:
It is often necessary for some code to be executed before eachevaluation of the while loop condition. This code is oftenduplicated outside the loop, as setup code that executes oncebefore entering the loop:<setupcode>while<condition>:<loopbody><setupcode>
That PEP was rejected because no syntax was found that was superiorto the following form:
whileTrue:<setupcode>ifnot<condition>:break<loopbody>
This PEP proposes a superior form, one that also has application tofor loops. It is superior because it makes the flow of control inloops more explicit, while preserving Python’s indentation aesthetic.
The syntax of the break and continue statements are extendedas follows:
break_stmt:"break"["if"expression]continue_stmt:"continue"["if"expression]
In addition, the syntax of the while statement is modified as follows:
while_stmt:while1_stmt|while2_stmtwhile1_stmt:"while"expression":"suite["else"":"suite]while2_stmt:"while"":"suite
Abreakif orcontinueif is executed if and only ifexpression evaluates to true.
Awhile statement with no expression loops until a break or returnis executed (or an error is raised), as if it were awhileTruestatement. Given that the loop can never terminate except in away that would not cause anelse suite to execute, noelsesuite is allowed in the expressionless form. If practical, itshould also be an error if the body of an expressionlesswhiledoes not contain at least onebreak orreturn statement.
The previous “best possible” form:
whileTrue:<setupcode>ifnot<condition>:break<loopbody>
could be formatted as:
whileTrue:<setupcode>ifnot<condition>:break<loopbody>
This is superficially almost identical to the form proposed by thisPEP:
while:<setupcode>breakifnot<condition><loopbody>
The significant difference here is that the loop flow controlkeyword appearsfirst in the line of code. This makes it easierto comprehend the flow of control in the loop at a glance, especiallywhen reading colorized code.
For example, this is a common code pattern, taken in this casefrom the tarfile module:
whileTrue:buf=self._read(self.bufsize)ifnotbuf:breakt.append(buf)
Reading this, we either see the break and possibly need to think aboutwhere the while is that it applies to, since the break is indentedunder the if, and then track backward to read the condition thattriggers it; or, we read the condition and only afterward discoverthat this condition changes the flow of the loop.
With the new syntax this becomes:
while:buf=self._read(self.bufsize)breakifnotbuft.append(buf)
Reading this we first see thebreak, which obviously applies tothe while since it is at the same level of indentation as the loopbody, and then we read the condition that causes the flow of controlto change.
Further, consider a more complex example from sre_parse:
whileTrue:c=self.nextself.__next()ifcisNone:ifnotresult:raiseself.error("missing group name")raiseself.error("missing%s, unterminated name"%terminator,len(result))ifc==terminator:ifnotresult:raiseself.error("missing group name",1)breakresult+=creturnresult
This is the natural way to write this code given current Pythonloop control syntax. However, givenbreakif, it would be morenatural to write this as follows:
while:c=self.nextself.__next()breakifcisNoneorc==terminatorresult+=cifnotresult:raiseself.error("missing group name")elifcisNone:raiseself.error("missing%s, unterminated name"%terminator,len(result))returnresult
This form moves the error handling out of the loop body, leaving theloop logic much more understandable. While it would certainly bepossible to write the code this way using the current syntax, theproposed syntax makes it more natural to write it in the clearer form.
The proposed syntax also provides a natural, Pythonic spelling ofthe classicrepeat...until<expression> construct found inother languages, and for which no good syntax has previously beenfound for Python:
while:...breakif<expression>
The tarfile module, for example, has a couple of “read until” loops likethe following:
whileTrue:s=self.__read(1)ifnotsors==NUL:break
With the new syntax this would read more clearly:
while:s=self.__read(1)breakifnotsors==NUL
The case for extending this syntax tocontinue is less strong,but buttressed by the value of consistency.
It is much more common for acontinue statement to be at theend of a multiline if suite, such as this example from zipfile
whileTrue:try:self.fp=io.open(file,filemode)exceptOSError:iffilemodeinmodeDict:filemode=modeDict[filemode]continueraisebreak
The only opportunity for improvement the new syntax would offer forthis loop would be the omission of theTrue token.
On the other hand, consider this example from uuid.py:
foriinrange(adapters.length):ncb.Reset()ncb.Command=netbios.NCBRESETncb.Lana_num=ord(adapters.lana[i])ifwin32wnet.Netbios(ncb)!=0:continuencb.Reset()ncb.Command=netbios.NCBASTATncb.Lana_num=ord(adapters.lana[i])ncb.Callname='*'.ljust(16)ncb.Buffer=status=netbios.ADAPTER_STATUS()ifwin32wnet.Netbios(ncb)!=0:continuestatus._unpack()bytes=status.adapter_address[:6]iflen(bytes)!=6:continuereturnint.from_bytes(bytes,'big')
This becomes:
foriinrange(adapters.length):ncb.Reset()ncb.Command=netbios.NCBRESETncb.Lana_num=ord(adapters.lana[i])continueifwin32wnet.Netbios(ncb)!=0ncb.Reset()ncb.Command=netbios.NCBASTATncb.Lana_num=ord(adapters.lana[i])ncb.Callname='*'.ljust(16)ncb.Buffer=status=netbios.ADAPTER_STATUS()continueifwin32wnet.Netbios(ncb)!=0status._unpack()bytes=status.adapter_address[:6]continueiflen(bytes)!=6returnint.from_bytes(bytes,'big')
This example indicates that there are non-trivial use cases wherecontinueif also improves the readability of the loop code.
It is probably significant to note that all of the examples selectedfor this PEP were found by grepping the standard library forwhileTrue andcontinue, and the relevant examples were found inthe first four modules inspected.
This document is placed in the public domain.
Source:https://github.com/python/peps/blob/main/peps/pep-0548.rst
Last modified:2025-02-01 08:59:27 GMT