This PEP is rejected.Seehttps://mail.python.org/pipermail/python-3000/2007-July/008663.html.
This PEP proposes support for labels in Python’sbreak andcontinue statements. It is inspired by labeledbreak andcontinue in other languages, and the author’s own infrequent butpersistent need for such a feature.
Thebreak statement allows the programmer to terminate a loopearly, and thecontinue statement allows the programmer to move tothe next iteration of a loop early. In Python currently,breakandcontinue can apply only to the innermost enclosing loop.
Adding support for labels to thebreak andcontinue statementsis a logical extension to the existing behavior of thebreak andcontinue statements. Labeledbreak andcontinue canimprove the readability and flexibility of complex code which usesnested loops.
For brevity’s sake, the examples and discussion in this PEP usuallyrefers to thebreak statement. However, all of the examples andmotivations apply equally to labeledcontinue.
If the programmer wishes to move to the next iteration of an outerenclosing loop, or terminate multiple loops at once, he or she has afew less-than elegant options.
Here’s one common way of imitating labeledbreak in Python (Forthis and future examples,... denotes an arbitrary number ofintervening lines of code):
foraina_list:time_to_break_out_of_a=False...forbinb_list:...ifcondition_one(a,b):break...ifcondition_two(a,b):time_to_break_out_of_a=Truebreak...iftime_to_break_out_of_a:break...
This requires five lines and an extra variable,time_to_break_out_of_a, to keep track of when to break out of theouter (a) loop. And those five lines are spread across many lines ofcode, making the control flow difficult to understand.
This technique is also error-prone. A programmer modifying this codemight inadvertently put new code after the end of the inner (b) loopbut before the test fortime_to_break_out_of_a, instead of afterthe test. This means that code which should have been skipped bybreaking out of the outer loop gets executed incorrectly.
This could also be written with an exception. The programmer woulddeclare a special exception, wrap the inner loop in a try, and catchthe exception and break when you see it:
classBreakOutOfALoop(Exception):passforaina_list:...try:forbinb_list:...ifcondition_one(a,b):break...ifcondition_two(a,b):raiseBreakOutOfALoop...exceptBreakOutOfALoop:break...
Again, though; this requires five lines and a new, single-purposeexception class (instead of a new variable), and spreads basic controlflow out over many lines. And it breaks out of the inner loop withbreak and out of the other loop with an exception, which isinelegant.[1]
This next strategy might be the most elegant solution, assumingcondition_two() is inexpensive to compute:
foraina_list:...forbinb_list:...ifcondition_one(a,b):break...ifcondition_two(a,b):break...ifcondition_two(a,b)break...
Breaking twice is still inelegant. This implementation also relies onthe fact that the inner (b) loop bleeds b into the outer for loop,which (although explicitly supported) is both surprising to novices,and in my opinion counter-intuitive and poor practice.
The programmer must also still remember to put in both breaks oncondition two and not insert code before the second break. A singleconceptual action, breaking out of both loops on condition_two(),requires four lines of code at two indentation levels, possiblyseparated by many intervening lines at the end of the inner (b) loop.
Now, put aside whatever dislike you may have for other programminglanguages, and consider the syntax of labeledbreak andcontinue. In Perl:
ALOOP: foreach $a (@a_array){ ... BLOOP: foreach $b (@b_array){ ... if (condition_one($a,$b)){ last BLOOP; # same as plain old last; } ... if (condition_two($a,$b)){ last ALOOP; } ... } ...}(Notes: Perl useslast instead ofbreak. The BLOOP labelscould be omitted;last andcontinue apply to the innermostloop by default.)
PHP uses a number denoting the number of loops to break out of, ratherthan a label:
foreach ($a_array as $a){ .... foreach ($b_array as $b){ .... if (condition_one($a, $b)){ break 1; # same as plain old break } .... if (condition_two($a, $b)){ break 2; } .... } ...}C/C++, Java, and Ruby all have similar constructions.
The control flow regarding when to break out of the outer (a) loop isfully encapsulated in thebreak statement which gets executed whenthe break condition is satisfied. The depth of the break statementdoes not matter. Control flow is not spread out. No extra variables,exceptions, or re-checking or storing of control conditions isrequired. There is no danger that code will get inadvertentlyinserted after the end of the inner (b) loop and before the breakcondition is re-checked inside the outer (a) loop. These are thebenefits that labeledbreak andcontinue would bring toPython.
This PEP is not a proposal to add GOTO to Python. GOTO allows aprogrammer to jump to an arbitrary block or line of code, andgenerally makes control flow more difficult to follow. Althoughbreak andcontinue (with or without support for labels) can beconsidered a type of GOTO, it is much more restricted. Another Pythonconstruct,yield, could also be considered a form of GOTO – aneven less restrictive one. The goal of this PEP is to propose anextension to the existing control flow toolsbreak andcontinue, to make control flow easier to understand, not moredifficult.
Labeledbreak andcontinue cannot transfer control to anotherfunction or method. They cannot even transfer control to an arbitraryline of code in the current scope. Currently, they can only affectthe behavior of a loop, and are quite different and much morerestricted than GOTO. This extension allows them to affect anyenclosing loop in the current name-space, but it does not change theirbehavior to that of GOTO.
Under all of these proposals,break andcontinue by themselveswill continue to behave as they currently do, applying to theinnermost loop by default.
The for and while loop syntax will be followed by an optionalasorlabel (contextual) keyword[2] and then an identifier,which may be used to identify the loop out of which to break (or whichshould be continued).
Thebreak (andcontinue) statements will be followed by anoptional identifier that refers to the loop out of which to break (orwhich should be continued). Here is an example using theaskeyword:
foraina_listasa_loop:...forbinb_listasb_loop:...ifcondition_one(a,b):breakb_loop# same as plain old break...ifcondition_two(a,b):breaka_loop......
Or, withlabel instead ofas:
foraina_listlabela_loop:...forbinb_listlabelb_loop:...ifcondition_one(a,b):breakb_loop# same as plain old break...ifcondition_two(a,b):breaka_loop......
This has all the benefits outlined above. It requires modificationsto the language syntax: the syntax ofbreak andcontinuesyntax statements and for and while statements. It requires either anew conditional keywordlabel or an extension to the conditionalkeywordas.[3] It is unlikely to require any changes toexisting Python programs. Passing an identifier not defined in thelocal scope tobreak orcontinue would raise a NameError.
Rather than altering the syntax offor andwhile loops,break andcontinue would take a numeric argument denoting theenclosing loop which is being controlled, similar to PHP.
It seems more Pythonic to me forbreak andcontinue to referto loops indexing from zero, as opposed to indexing from one as PHPdoes.
foraina_list:...forbinb_list:...ifcondition_one(a,b):break0# same as plain old break...ifcondition_two(a,b):break1......
Passing a number that was too large, or less than zero, or non-integertobreak orcontinue would (probably) raise an IndexError.
This proposal would not require any changes to existing Pythonprograms.
The syntax ofbreak andcontinue would be altered to allowmultiplebreak and continue statements on the same line. Thus,breakbreak would break out of the first and second enclosingloops.
foraina_list:...forbinb_list:...ifcondition_one(a,b):break# plain old break...ifcondition_two(a,b):breakbreak......
This would also allow the programmer to break out of the inner loopand continue the next outermost simply by writingbreakcontinue,[4] and so on. I’m not sure what exception would beraised if the programmer used morebreak orcontinuestatements than existing loops (perhaps a SyntaxError?).
I expect this proposal to get rejected because it will be judged toodifficult to understand.
This proposal would not require any changes to existing Pythonprograms.
Rather than embellishing for and while loop syntax with labels, theprogrammer wishing to use labeled breaks would be required to createthe iterator explicitly and assign it to an identifier if he or shewanted tobreak out of orcontinue that loop from within adeeper loop.
a_iter=iter(a_list)foraina_iter:...b_iter=iter(b_list)forbinb_iter:...ifcondition_one(a,b):breakb_iter# same as plain old break...ifcondition_two(a,b):breaka_iter......
Passing a non-iterator object tobreak orcontinue would raisea TypeError; and a nonexistent identifier would raise a NameError.This proposal requires only one extra line to create a labeled loop,and no extra lines to break out of a containing loop, and no changesto existing Python programs.
This is a variant of Proposal D. Iterators would need be createdexplicitly if anything other that the most basic use ofbreak andcontinue was required. Instead of modifying the syntax ofbreak andcontinue,.break() and.continue() methodscould be added to the Iterator type.
a_iter=iter(a_list)foraina_iter:...b_iter=iter(b_list)forbinb_iter:...ifcondition_one(a,b):b_iter.break()# same as plain old break...ifcondition_two(a,b):a_iter.break()......
I expect that this proposal will get rejected on the grounds of sheerugliness. However, it requires no changes to the language syntaxwhatsoever, nor does it require any changes to existing Pythonprograms.
I have never looked at the Python language implementation itself, so Ihave no idea how difficult this would be to implement. If this PEP isaccepted, but no one is available to write the feature, I will try toimplement it myself.
as,label,labeled,loop,name,named,walrus, whatever.as in a similar context has been proposed here,http://sourceforge.net/tracker/index.php?func=detail&aid=1714448&group_id=5470&atid=355470but to my knowledge this idea has not been written up as a PEP.continue would beallowed, and only at the end of a sequence of breaks.continuebreak orcontinuecontinue makes no sense.This issue has come up before, although it has never been resolved, tomy knowledge.
do...while loopsThis document has been placed in the public domain.
Source:https://github.com/python/peps/blob/main/peps/pep-3136.rst
Last modified:2025-02-01 08:59:27 GMT