-
-
Notifications
You must be signed in to change notification settings - Fork 30.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
For-else deserves its own section in the tutorial #123946
Conversation
Doc/tutorial/controlflow.rst
Outdated
the ``for`` loop, **not** the ``if`` statement.) | ||
|
||
One way to think of the else clause is to imagine it paired with the ``if`` | ||
inside the loop. If you conceptually unroll the loop, you have an if/if/if/else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As noted in Discourse, I think the concept of “loop unrolling” may sound too foreign to novices reading a tutorial. The paragraph may serve the purpose just as well without this sentence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about:
As the loop executes, it will run a sequence like
if/if/if/else
. Theif
is inside the loop, encountered a number of times. If the condition is ever true, abreak
will happen. If the condition is never true, the else clause outside the loop will execute.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes that sounds to be in much plainer English to me. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recently wrote about this elsewhere and even included an example:
class Integer:
__fallback_value__ = 0
__inner_value__ = None
def __init__(self, *args) -> None:
"""This constructor method accepts any number of positional arguments.
It then implements the under-used and underappreciated 'for-loop'
ending with an 'else' clause. The code in the 'else' block runs
after the loop completes. The point is that the 'break' keyword also
applies to this block. So if 'break' is encountered, the code in the
'else' block does not run. To translate to natural language:
'Go through each positional argument and when you find an integer,
assign it to the inner value. Use the fallback value if you have not found any integer
after looking through each positional argument.'
It is the opinion of this author that the 'else' clause in a loop is
both underused and underappreciated."""
for arg in args:
if isinstance(arg, int):
self.__inner_value__ = arg
break
else:
self.__inner_value__ = self.__fallback_value__
Hope this helps in some small way!
the condition is ever true, a ``break`` will happen. If the condition is never | ||
true, the ``else`` clause outside the loop will execute. | ||
|
||
When used with a loop, the ``else`` clause has more in common with the ``else`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this paragraph necessary? Many readers of the tutorial will not be familiar with try/else, so I'm not sure this helps many people.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't expect people to read purely linearly, and this could help cement the semantics in the reader's mind.
Co-authored-by: Jelle Zijlstra <[email protected]>
Thanks @nedbat for the PR 🌮🎉.. I'm working now to backport this PR to: 3.12. |
Thanks @nedbat for the PR 🌮🎉.. I'm working now to backport this PR to: 3.13. |
* For-else deserves its own section in the tutorial * remove mention of unrolling the loop * Update Doc/tutorial/controlflow.rst Co-authored-by: Jelle Zijlstra <[email protected]> --------- (cherry picked from commit ffdc80e) Co-authored-by: Ned Batchelder <[email protected]> Co-authored-by: Jelle Zijlstra <[email protected]>
GH-124563 is a backport of this pull request to the 3.12 branch. |
* For-else deserves its own section in the tutorial * remove mention of unrolling the loop * Update Doc/tutorial/controlflow.rst Co-authored-by: Jelle Zijlstra <[email protected]> --------- (cherry picked from commit ffdc80e) Co-authored-by: Ned Batchelder <[email protected]> Co-authored-by: Jelle Zijlstra <[email protected]>
GH-124564 is a backport of this pull request to the 3.13 branch. |
* main: (69 commits) Add "annotate" SET_FUNCTION_ATTRIBUTE bit to dis. (python#124566) pythongh-124412: Add helpers for converting annotations to source format (python#124551) pythongh-119180: Disallow instantiation of ConstEvaluator objects (python#124561) For-else deserves its own section in the tutorial (python#123946) Add 3.13 as a version option to the crash issue template (python#124560) pythongh-123242: Note that type.__annotations__ may not exist (python#124557) pythongh-119180: Make FORWARDREF format look at __annotations__ first (python#124479) pythonGH-58058: Add quick reference for `ArgumentParser` to argparse docs (pythongh-124227) pythongh-41431: Add `datetime.time.strptime()` and `datetime.date.strptime()` (python#120752) pythongh-102450: Add ISO-8601 alternative for midnight to `fromisoformat()` calls. (python#105856) pythongh-124370: Add "howto" for free-threaded Python (python#124371) pythongh-121277: Allow `.. versionadded:: next` in docs (pythonGH-121278) pythongh-119400: make_ssl_certs: update reference test data automatically, pass in expiration dates as parameters python#119400 (pythonGH-119401) pythongh-119180: Avoid going through AST and eval() when possible in annotationlib (python#124337) pythongh-124448: Update Windows builds to use Tcl/Tk 8.6.15 (pythonGH-124449) pythongh-123884 Tee of tee was not producing n independent iterators (pythongh-124490) pythongh-124378: Update test_ttk for Tcl/Tk 8.6.15 (pythonGH-124542) pythongh-124513: Check args in framelocalsproxy_new() (python#124515) pythongh-101100: Add a table of class attributes to the "Custom classes" section of the data model docs (python#124480) Doc: Use ``major.minor`` for documentation distribution archive filenames (python#124489) ...
…124563) (cherry picked from commit ffdc80e) Co-authored-by: Ned Batchelder <[email protected]> Co-authored-by: Jelle Zijlstra <[email protected]>
…124564) For-else deserves its own section in the tutorial (GH-123946) * For-else deserves its own section in the tutorial * remove mention of unrolling the loop * Update Doc/tutorial/controlflow.rst --------- (cherry picked from commit ffdc80e) Co-authored-by: Ned Batchelder <[email protected]> Co-authored-by: Jelle Zijlstra <[email protected]>
@nedbat minor feedback: it's good practice to clean up the commit message before merging so that the git log is more understandable. GitHub's default includes the titles of all the commits, which are often not very informative. In this case, I would have shortened the commit message to just:
|
I complete agree that break/continue should be separated from else. But I am sorry I did not see this earlier. Existing lines 203 to 205 after the patch are incomplete. 'else' is paired with any loop exit.
Ned, do you want to make another PR, or should I? |
📚 Documentation preview 📚: https://cpython-previews--123946.org.readthedocs.build/