bpo-40576: Align docs for list.sort and sorted

Align the documentation for both `list.sort` and `sorted` since the
latter's C implementation delegates to the C implementation of the
former, in both docstrings, the library docs, and tutorial.

Add a note about how reverse and sort stability interplay, as
this is an easily forgotten edge case and may not necessarily always be
desired.

bltinmodule.c, listobject.c.h:

* Instead of saying "equal elements" in the note about sort stability,
  we standardize on the "compare equal" phrasing from functions.rst,
  which is more precise phrasing that acknowledges that sorting is
  controlled by `key`.

* "ascending or descending" is dropped from the explanation of `key` in
  `list.sort`, because that's controlled by `reverse`, not `key`.

library/functions.rst:

* Fix the type signature of `sorted`.
* Redirect the documentation to `list.sort`.

library/stdtypes.rst:

* Fix the type signature of `list.sort`.
* Replace the "as if each comparison were reversed" language with
  "descending order" for consistency. (Also, technically reversed isn't
  quite true: == comparisons aren't reversed ;).)

tutorial/datastructures.rst:

* Point the reference for `list.sort` to `list.sort`, instead of
  `sorted`.

The set of modified files/locations was determined using:

    grep -C3 -rnE '`(list\.sort|sorted)`' . | grep -v 'howto/sorting\|whatsnew'

The example of sort stability is included in functions.rst
but omitted from the docstrings deliberately: you can only really get to
it via `help()` or `pydoc`, which I suspect tend to be used by people
who know what sort stability is. (Incidentally, in the discussion on
pythonGH-8516, the last update to the list.sort docstring, rhettinger
also expresses the POV that further discussion of sort stability belongs
in extended docs like FAQs/HOWTOs.)
This commit is contained in:
Samuel Lijin 2020-05-09 04:02:54 -07:00
parent 1e7e4519a8
commit 468c836ec0
6 changed files with 66 additions and 41 deletions

View File

@ -538,6 +538,7 @@ wrapped list must not change to avoid anomalies. Don't do this unless you are
prepared to think hard about the requirements and the consequences of not
meeting them correctly. Consider yourself warned.
.. _faq-list-sort-return-type:
Why doesn't list.sort() return the sorted list?
-----------------------------------------------

View File

@ -1511,26 +1511,18 @@ are always available. They are listed here in alphabetical order.
:func:`itertools.islice` for an alternate version that returns an iterator.
.. function:: sorted(iterable, *, key=None, reverse=False)
.. function:: sorted(iterable, /, *, key=None, reverse=False)
Return a new sorted list from the items in *iterable*.
Return a new list containing all items from *iterable* in ascending order.
Has two optional arguments which must be specified as keyword arguments.
Roughly equivalent to::
*key* specifies a function of one argument that is used to extract a comparison
key from each element in *iterable* (for example, ``key=str.lower``). The
default value is ``None`` (compare the elements directly).
def sorted(iterable, key=None, reverse=False):
l = list(iterable)
l.sort(key=key, reverse=reverse)
return l
*reverse* is a boolean value. If set to ``True``, then the list elements are
sorted as if each comparison were reversed.
Use :func:`functools.cmp_to_key` to convert an old-style *cmp* function to a
*key* function.
The built-in :func:`sorted` function is guaranteed to be stable. A sort is
stable if it guarantees not to change the relative order of elements that
compare equal --- this is helpful for sorting in multiple passes (for
example, sort by department, then by salary grade).
See :meth:`list.sort` for an explanation of the arguments.
For sorting examples and a brief sorting tutorial, see :ref:`sortinghowto`.

View File

@ -1175,7 +1175,7 @@ application).
:ref:`mutable <typesseq-mutable>` sequence operations. Lists also provide the
following additional method:
.. method:: list.sort(*, key=None, reverse=False)
.. method:: list.sort(self, /, *, key=None, reverse=False)
This method sorts the list in place, using only ``<`` comparisons
between items. Exceptions are not suppressed - if any comparison operations
@ -1185,28 +1185,46 @@ application).
:meth:`sort` accepts two arguments that can only be passed by keyword
(:ref:`keyword-only arguments <keyword-only_parameter>`):
*key* specifies a function of one argument that is used to extract a
comparison key from each list element (for example, ``key=str.lower``).
The key corresponding to each item in the list is calculated once and
then used for the entire sorting process. The default value of ``None``
means that list items are sorted directly without calculating a separate
key value.
*key* specifies a function of one argument used to generate a comparison
key for each list element (e.g. ``key=str.lower``) to use when sorting.
The key for each element in the list is calculated exactly once and then
used for each comparison invoked by the sort.
The default value of ``None`` means that list elements are compared
directly to each other without calculating a separate comparison key.
The :func:`functools.cmp_to_key` utility is available to convert a 2.x
style *cmp* function to a *key* function.
*reverse* is a boolean value. If set to ``True``, then the list elements
are sorted as if each comparison were reversed.
are sorted in descending order, preserving forward sort stability when
applicable (see below for an example).
This method modifies the sequence in place for economy of space when
:meth:`sort` modifies the sequence in place for economy of space when
sorting a large sequence. To remind users that it operates by side
effect, it does not return the sorted sequence (use :func:`sorted` to
explicitly request a new sorted list instance).
effect, it does not return the sorted sequence (see
:ref:`faq-list-sort-return-type` for an explanation).
The :meth:`sort` method is guaranteed to be stable. A sort is stable if it
guarantees not to change the relative order of elements that compare equal
--- this is helpful for sorting in multiple passes (for example, sort by
department, then by salary grade).
:func:`sorted` (which effectively delegates to :meth:`sort`) can be used
to explicitly request a new sorted list instance.
The :meth:`sort` method (and consequently also :func:`sorted`) is
guaranteed to be stable, which means that the relative order of elements
that compare equal is preserved::
>>> sorted([7, 5.2, 5.1, 5.3], key=round)
[5.2, 5.1, 5.3, 7]
When *reverse* is set to ``True``, forward stability is preserved::
>>> sorted([7, 5.2, 5.1, 5.3], key=round, reverse=True)
[7, 5.2, 5.1, 5.3]
Note that this behaves differently than simply reversing a sort::
>>> list(reversed(sorted([7, 5.2, 5.1, 5.3], key=round)))
[7, 5.3, 5.1, 5.2]
For sorting examples and a brief sorting tutorial, see :ref:`sortinghowto`.

View File

@ -82,7 +82,7 @@ objects:
:noindex:
Sort the items of the list in place (the arguments can be used for sort
customization, see :func:`sorted` for their explanation).
customization, see :meth:`list.sort` for their explanation).
.. method:: list.reverse()

View File

@ -158,13 +158,15 @@ PyDoc_STRVAR(list_sort__doc__,
"\n"
"Sort the list in ascending order and return None.\n"
"\n"
"The sort is in-place (i.e. the list itself is modified) and stable (i.e. the\n"
"order of two equal elements is maintained).\n"
"The sort is in-place (i.e. the list itself is modified) and guaranteed to be\n"
"stable (i.e. the relative order of elements that compare equal is preserved).\n"
"\n"
"If a key function is given, apply it once to each list item and sort them,\n"
"ascending or descending, according to their function values.\n"
"If a key function is given, apply it once to each list element and use\n"
"the results as the comparison keys when sorting.\n"
"\n"
"The reverse flag can be set to sort in descending order.");
"If reverse is True, instead sort in descending order. Note that forward\n"
"sort stability is preserved when doing so.\n"
);
#define LIST_SORT_METHODDEF \
{"sort", (PyCFunction)(void(*)(void))list_sort, METH_FASTCALL|METH_KEYWORDS, list_sort__doc__},

View File

@ -2198,8 +2198,13 @@ sorted as builtin_sorted
Return a new list containing all items from the iterable in ascending order.
A custom key function can be supplied to customize the sort order, and the
reverse flag can be set to request the result in descending order.
The sort is guaranteed to be stable (i.e. the relative order of elements
that compare equal is preserved).
If a key function is given, apply it once to each element and use the results
as the comparison keys when sorting.
If reverse is True, instead sort in descending order.
[end disabled clinic input]*/
PyDoc_STRVAR(builtin_sorted__doc__,
@ -2208,8 +2213,15 @@ PyDoc_STRVAR(builtin_sorted__doc__,
"\n"
"Return a new list containing all items from the iterable in ascending order.\n"
"\n"
"A custom key function can be supplied to customize the sort order, and the\n"
"reverse flag can be set to request the result in descending order.");
"The sort is guaranteed to be stable (i.e. the relative order of elements\n"
"that compare equal is preserved).\n"
"\n"
"If a key function is given, apply it once to each element and use the results\n"
"as the comparison keys when sorting.\n"
"\n"
"If reverse is True, instead sort in descending order. Note that forward\n"
"sort stability is preserved when doing so.\n"
);
#define BUILTIN_SORTED_METHODDEF \
{"sorted", (PyCFunction)(void(*)(void))builtin_sorted, METH_FASTCALL | METH_KEYWORDS, builtin_sorted__doc__},