Skip to content

Commit c3b7eb0

Browse files
miss-islingtonencukouhugovk
authored
[3.14] gh-154661: Reorganize difflib documentation (GH-154662) (#154806)
Co-authored-by: Petr Viktorin <encukou@gmail.com> Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
1 parent 6b8451f commit c3b7eb0

1 file changed

Lines changed: 132 additions & 104 deletions

File tree

Doc/library/difflib.rst

Lines changed: 132 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -17,49 +17,86 @@
1717

1818
--------------
1919

20-
This module provides classes and functions for comparing sequences. It
21-
can be used for example, for comparing files, and can produce information
22-
about file differences in various formats, including HTML and context and unified
23-
diffs. For comparing directories and files, see also, the :mod:`filecmp` module.
24-
25-
26-
.. class:: SequenceMatcher
27-
:noindex:
28-
29-
This is a flexible class for comparing pairs of sequences of any type, so long
30-
as the sequence elements are :term:`hashable`. The basic algorithm predates, and is a
31-
little fancier than, an algorithm published in the late 1980's by Ratcliff and
32-
Obershelp under the hyperbolic name "gestalt pattern matching." The idea is to
33-
find the longest contiguous matching subsequence that contains no "junk"
34-
elements; these "junk" elements are ones that are uninteresting in some
35-
sense, such as blank lines or whitespace. (Handling junk is an
36-
extension to the Ratcliff and Obershelp algorithm.) The same
37-
idea is then applied recursively to the pieces of the sequences to the left and
38-
to the right of the matching subsequence. This does not yield minimal edit
39-
sequences, but does tend to yield matches that "look right" to people.
40-
41-
**Timing:** The basic Ratcliff-Obershelp algorithm is cubic time in the worst
42-
case and quadratic time in the expected case. :class:`SequenceMatcher` is
43-
quadratic time for the worst case and has expected-case behavior dependent in a
44-
complicated way on how many elements the sequences have in common; best case
45-
time is linear.
46-
47-
**Junk**: :class:`SequenceMatcher` accepts an ``isjunk`` predicate and an
48-
``autojunk`` flag. Items that are considered as junk will not be considered
49-
to find similar content blocks. This can produce better results for humans
50-
(typically breaking on whitespace) and faster (because it reduces the number
51-
of possible combinations). But it can also cause pathological cases where
52-
too many items considered junk cause an unexpectedly large (but correct)
53-
diff result.
54-
You should consider tuning them or turning them off depending on your data.
55-
Moreover, only the second sequence is inspected for junk. This causes the diff
56-
output to not be symmetrical.
57-
When ``autojunk=True``, it will consider as junk the items that account for more
58-
than 1% of the sequence, if it is at least 200 items long.
20+
This module provides classes and functions for comparing sequences.
21+
Most of them compare sequences of text lines (for example lists of strings,
22+
or :term:`file objects <file object>`) and
23+
produce :dfn:`diffs` -- reports on the differences.
24+
Diffs can be produced in in various formats, including HTML and context
25+
and unified diffs -- formats produced by tools like
26+
:manpage:`diff <diff(1)>` and :manpage:`git diff <git-diff(1)>`.
5927

60-
.. versionchanged:: 3.2
61-
Added the *autojunk* parameter.
28+
Comparisons are done using a matching algorithm implemented in
29+
:class:`SequenceMatcher` -- a flexible class for comparing pairs of sequences
30+
of any type, not just text, so long as the sequence elements are
31+
:term:`hashable`.
32+
33+
34+
.. _difflib-junk:
35+
36+
Junk heuristic
37+
--------------
38+
39+
:mod:`!difflib` uses a :dfn:`junk` heuristic: some items are deemed to be
40+
:dfn:`junk`, and ignored when searching for similarities.
41+
Ideally, these are uninteresting or common items, such as blank lines
42+
or whitespace.
43+
44+
This heuristic can speed the algorithm up (because it reduces the number of
45+
possible combinations) and it can produce results that are more understandable
46+
for humans (typically breaking on whitespace).
47+
But it can also cause pathological cases:
48+
49+
- Inappropriately chosen junk items can cause an unexpectedly **large** (but
50+
still correct) result.
51+
- The default heuristic is **asymmetric**: only the second sequence is
52+
inspected when determining what is considered junk, so comparing A to B can
53+
give different results than comparing B to A and reversing the result.
54+
55+
By default, if the second input sequence is at least 200 items long, items
56+
that account for more than 1% it are considered *junk*.
57+
58+
Depending on your data, you should consider turning this heuristic off
59+
(setting :class:`~difflib.SequenceMatcher`'s *autojunk* argument to to ``False``)
60+
or tuning it (using the *isjunk* argument, perhaps to one of the
61+
:ref:`predefined functions <difflib-isjunk-functions>`).
62+
63+
64+
The :mod:`!difflib` algorithm
65+
-----------------------------
66+
67+
The algorithm used in :class:`SequenceMatcher` predates, and is a little
68+
fancier than, an algorithm published in the late 1980s by Ratcliff and
69+
Obershelp under the hyperbolic name "gestalt pattern matching."
70+
The idea is to find the longest contiguous subsequence common to both inputs,
71+
then recursively handle the pieces of the sequences to the left and to the
72+
right of the matching subsequence.
73+
74+
.. seealso::
75+
76+
`Pattern Matching: The Gestalt Approach <https://jacobfilipp.com/DrDobbs/articles/DDJ/1988/8807/8807c/8807c.htm>`_
77+
Discussion of a similar algorithm by John W. Ratcliff and D. E. Metzener. This
78+
was published in Dr. Dobb's Journal in July, 1988.
79+
80+
As an extension to the Ratcliff and Obershelp algorithm, :mod:`!difflib`
81+
searches for the longest *junk-free* contiguous subsequence.
82+
See the :ref:`difflib-junk` section for details.
83+
84+
.. impl-detail:: Timing
6285

86+
The basic Ratcliff-Obershelp algorithm is cubic time in the worst
87+
case and quadratic time in the expected case.
88+
:mod:`difflib`'s algorithm is quadratic time for the worst case and has
89+
expected-case behavior dependent in a complicated way on how many elements
90+
the sequences have in common;
91+
best case time is linear.
92+
93+
94+
.. _difflib-diff-generation:
95+
96+
Diff generation
97+
---------------
98+
99+
.. _differ-objects:
63100

64101
.. class:: Differ
65102

@@ -86,6 +123,47 @@ diffs. For comparing directories and files, see also, the :mod:`filecmp` module.
86123
and were not present in either input sequence. These lines can be confusing if
87124
the sequences contain whitespace characters, such as spaces, tabs or line breaks.
88125

126+
Note that :class:`Differ`\ -generated deltas make no claim to be **minimal**
127+
diffs. To the contrary, minimal diffs are often counter-intuitive for humans,
128+
because they synch up anywhere possible, sometimes at accidental matches
129+
100 pages apart.
130+
Restricting synch points to contiguous matches preserves some notion of
131+
locality, at the occasional cost of producing a longer diff.
132+
133+
The :class:`Differ` class has this constructor:
134+
135+
.. method:: __init__(linejunk=None, charjunk=None)
136+
137+
Optional keyword parameters *linejunk* and *charjunk* are for filter functions
138+
(or ``None``):
139+
140+
*linejunk*: A function that accepts a single string argument, and returns true
141+
if the string is junk. The default is ``None``, meaning that no line is
142+
considered junk.
143+
144+
*charjunk*: A function that accepts a single character argument (a string of
145+
length 1), and returns true if the character is junk. The default is ``None``,
146+
meaning that no character is considered junk.
147+
148+
These junk-filtering functions speed up matching to find
149+
differences and do not cause any differing lines or characters to
150+
be ignored. Read the description of the
151+
:meth:`~SequenceMatcher.find_longest_match` method's *isjunk*
152+
parameter for an explanation.
153+
154+
:class:`Differ` objects are used (deltas generated) via a single method:
155+
156+
157+
.. method:: Differ.compare(a, b)
158+
159+
Compare two sequences of lines, and generate the delta (a sequence of lines).
160+
161+
Each sequence must contain individual single-line strings ending with
162+
newlines. Such sequences can be obtained from the
163+
:meth:`~io.IOBase.readlines` method of file-like objects. The generated
164+
delta also consists of newline-terminated strings, ready to be
165+
printed as-is via the :meth:`~io.IOBase.writelines` method of a
166+
file-like object.
89167

90168
.. class:: HtmlDiff
91169

@@ -345,6 +423,12 @@ diffs. For comparing directories and files, see also, the :mod:`filecmp` module.
345423

346424
.. versionadded:: 3.5
347425

426+
427+
.. _difflib-isjunk-functions:
428+
429+
Junk definition functions
430+
-------------------------
431+
348432
.. function:: IS_LINE_JUNK(line)
349433

350434
Return ``True`` for ignorable lines. The line *line* is ignorable if *line* is
@@ -359,21 +443,11 @@ diffs. For comparing directories and files, see also, the :mod:`filecmp` module.
359443
parameter *charjunk* in :func:`ndiff`.
360444

361445

362-
.. seealso::
363-
364-
`Pattern Matching: The Gestalt Approach <https://jacobfilipp.com/DrDobbs/articles/DDJ/1988/8807/8807c/8807c.htm>`_
365-
Discussion of a similar algorithm by John W. Ratcliff and D. E. Metzener. This
366-
was published in Dr. Dobb's Journal in July, 1988.
367-
368-
369446
.. _sequence-matcher:
370447

371448
SequenceMatcher objects
372449
-----------------------
373450

374-
The :class:`SequenceMatcher` class has this constructor:
375-
376-
377451
.. class:: SequenceMatcher(isjunk=None, a='', b='', autojunk=True)
378452

379453
Optional argument *isjunk* must be ``None`` (the default) or a one-argument
@@ -584,10 +658,13 @@ are always at least as large as :meth:`~SequenceMatcher.ratio`:
584658
1.0
585659

586660

661+
Examples
662+
--------
663+
587664
.. _sequencematcher-examples:
588665

589666
SequenceMatcher examples
590-
------------------------
667+
........................
591668

592669
This example compares two strings, considering blanks to be "junk":
593670

@@ -635,59 +712,10 @@ If you want to know how to change the first sequence into the second, use
635712
built with :class:`SequenceMatcher`.
636713

637714

638-
.. _differ-objects:
639-
640-
Differ objects
641-
--------------
642-
643-
Note that :class:`Differ`\ -generated deltas make no claim to be **minimal**
644-
diffs. To the contrary, minimal diffs are often counter-intuitive, because they
645-
synch up anywhere possible, sometimes accidental matches 100 pages apart.
646-
Restricting synch points to contiguous matches preserves some notion of
647-
locality, at the occasional cost of producing a longer diff.
648-
649-
The :class:`Differ` class has this constructor:
650-
651-
652-
.. class:: Differ(linejunk=None, charjunk=None)
653-
:noindex:
654-
655-
Optional keyword parameters *linejunk* and *charjunk* are for filter functions
656-
(or ``None``):
657-
658-
*linejunk*: A function that accepts a single string argument, and returns true
659-
if the string is junk. The default is ``None``, meaning that no line is
660-
considered junk.
661-
662-
*charjunk*: A function that accepts a single character argument (a string of
663-
length 1), and returns true if the character is junk. The default is ``None``,
664-
meaning that no character is considered junk.
665-
666-
These junk-filtering functions speed up matching to find
667-
differences and do not cause any differing lines or characters to
668-
be ignored. Read the description of the
669-
:meth:`~SequenceMatcher.find_longest_match` method's *isjunk*
670-
parameter for an explanation.
671-
672-
:class:`Differ` objects are used (deltas generated) via a single method:
673-
674-
675-
.. method:: Differ.compare(a, b)
676-
677-
Compare two sequences of lines, and generate the delta (a sequence of lines).
678-
679-
Each sequence must contain individual single-line strings ending with
680-
newlines. Such sequences can be obtained from the
681-
:meth:`~io.IOBase.readlines` method of file-like objects. The delta
682-
generated also consists of newline-terminated strings, ready to be
683-
printed as-is via the :meth:`~io.IOBase.writelines` method of a
684-
file-like object.
685-
686-
687715
.. _differ-examples:
688716

689717
Differ example
690-
--------------
718+
..............
691719

692720
This example compares two texts. First we set up the texts, sequences of
693721
individual single-line strings ending with newlines (such sequences can also be
@@ -754,14 +782,14 @@ As a single multi-line string it looks like this:
754782
.. _difflib-interface:
755783

756784
A command-line interface to difflib
757-
-----------------------------------
785+
...................................
758786

759787
This example shows how to use difflib to create a ``diff``-like utility.
760788

761789
.. literalinclude:: ../includes/diff.py
762790

763791
ndiff example
764-
-------------
792+
.............
765793

766794
This example shows how to use :func:`difflib.ndiff`.
767795

0 commit comments

Comments
 (0)