difflib — Помощники для вычисления дельт¶
Исходный код: Lib/difflib.py
Этот модуль предоставляет классы и функции для сравнения последовательностей. Его можно использовать, например, для сравнения файлов, и он может генерировать информацию о различиях в файлах в различных форматах, включая HTML, контекст и унифицированные различия. Для сравнения каталогов и файлов смотрите также модуль filecmp.
- class difflib.SequenceMatcher
Это гибкий класс для сравнения пар последовательностей любого типа, при условии, что элементы последовательности равны hashable. Базовый алгоритм предшествует алгоритму, опубликованному в конце 1980-х годов Рэтклиффом и Обершелпом под гиперболическим названием «сопоставление гештальт-паттернов», и немного более причудлив по сравнению с ним. Идея состоит в том, чтобы найти самую длинную непрерывную совпадающую подпоследовательность, которая не содержит «ненужных» элементов; эти «ненужные» элементы в некотором смысле неинтересны, например, пустые строки или пробелы. (Обработка нежелательной информации является расширением алгоритма Ратклиффа и Обершелпа.) Затем та же идея рекурсивно применяется к фрагментам последовательностей слева и справа от соответствующей подпоследовательности. Это не приводит к минимальным последовательностям редактирования, но, как правило, приводит к совпадениям, которые «выглядят правильно» для людей.
** Хронометраж:** Основной алгоритм Ратклиффа-Обершелпа использует кубическое время в наихудшем случае и квадратичное время в ожидаемом случае.
SequenceMatcher- квадратичное время в наихудшем случае, и его поведение в ожидаемом случае сложным образом зависит от того, сколько элементов имеют общие последовательности.; в лучшем случае время является линейным.Автоматическая эвристика нежелательной информации:
SequenceMatcherподдерживает эвристику, которая автоматически рассматривает определенные элементы последовательности как нежелательные. Эвристика подсчитывает, сколько раз каждый отдельный элемент появляется в последовательности. Если количество дубликатов товара (после первого) составляет более 1% от всей последовательности и длина последовательности составляет не менее 200 товаров, этот товар помечается как «популярный» и рассматривается как нежелательный для целей сопоставления последовательности. Эту эвристику можно отключить, установив для аргументаautojunkзначениеFalseпри созданииSequenceMatcher.Изменено в версии 3.2: Добавлен параметр автозапуск.
- class difflib.Differ¶
Это класс для сравнения последовательностей строк текста и создания удобочитаемых различий или дельт. Different использует
SequenceMatcherкак для сравнения последовательностей строк, так и для сравнения последовательностей символов в похожих (почти совпадающих) строках.Каждая строка дельты
Differначинается с двухбуквенного кода:Код
Значение
'- 'строка, уникальная для последовательности 1
'+ 'строка, уникальная для последовательности 2
' 'линия, общая для обеих последовательностей
'? 'строка, отсутствующая ни в одной из входных последовательностей
Строки, начинающиеся с «
?», указывают на внутренние различия, которых не было ни в одной из введенных последовательностей. Эти строки могут сбивать с толку, если последовательности содержат символы табуляции.
- class difflib.HtmlDiff¶
Этот класс может быть использован для создания HTML-таблицы (или полного HTML-файла, содержащего таблицу), показывающей параллельное, построчное сравнение текста с выделением изменений между строками и внутри строки. Таблица может быть создана как в режиме полной, так и в режиме контекстных различий.
Конструктором для этого класса является:
- __init__(tabsize=8, wrapcolumn=None, linejunk=None, charjunk=IS_CHARACTER_JUNK)¶
Инициализирует экземпляр
HtmlDiff.tabsize является необязательным аргументом ключевого слова для указания интервала между концами табуляции и по умолчанию равен
8.wrapcolumn - необязательное ключевое слово для указания номера столбца, в котором строки прерываются и переносятся, по умолчанию используется
None, в котором строки не переносятся.linejunk и charjunk являются необязательными ключевыми аргументами, передаваемыми в
ndiff()(используютсяHtmlDiffдля создания параллельных HTML-различий). Значения и описания аргументов по умолчанию приведены в документацииndiff().
Следующие методы являются общедоступными:
- make_file(fromlines, tolines, fromdesc='', todesc='', context=False, numlines=5, *, charset='utf-8')¶
Сравнивает fromlines и tolines (списки строк) и возвращает строку, которая представляет собой полный HTML-файл, содержащий таблицу, показывающую построчные различия с выделенными изменениями между строками и внутри строки.
fromdesc и todesc являются необязательными аргументами ключевых слов для указания строк заголовка столбца from/to файла (по умолчанию используется пустая строка).
context и numlines являются необязательными аргументами ключевого слова. Установите для параметра context значение
True, если необходимо отобразить контекстные различия, в противном случае по умолчанию используется значениеFalseдля отображения полных файлов. numlines по умолчанию имеет значение5. Когда значение context равноTrue, numlines управляет количеством контекстных строк, которые окружают выделенные различия. Когда значение context равноFalsenumlines определяет количество строк, которые отображаются перед выделением различий при использовании гиперссылок «next» (значение, равное нулю, приведет к тому, что гиперссылки «next» разместят следующую выделенную разницу в верхней части браузера без каких-либо начальных строк). контекст).Примечание
fromdesc и todesc интерпретируются как неэкранированный HTML и должны быть должным образом экранированы при получении входных данных из ненадежных источников.
Изменено в версии 3.5: кодировка Добавлен аргумент, содержащий только ключевое слово. Кодировка HTML-документа по умолчанию изменена с
'ISO-8859-1'на'utf-8'.
- make_table(fromlines, tolines, fromdesc='', todesc='', context=False, numlines=5)¶
Сравнивает fromlines и tolines (списки строк) и возвращает строку, которая представляет собой полную HTML-таблицу, показывающую построчные различия с выделенными изменениями между строками и внутри строки.
Аргументы для этого метода те же, что и для метода
make_file().
Tools/scripts/diff.pyявляется интерфейсом командной строки для этого класса и содержит хороший пример его использования.
- difflib.context_diff(a, b, fromfile='', tofile='', fromfiledate='', tofiledate='', n=3, lineterm='\n')¶
Сравните a и b (списки строк); верните дельту (a generator, генерирующую дельта-строки) в формате контекстной разницы.
Контекстные различия - это компактный способ отображения только тех строк, которые были изменены, плюс несколько строк контекста. Изменения отображаются в виде «до» и «после». Количество контекстных строк задается значением n, которое по умолчанию равно трем.
По умолчанию управляющие строки diff (те, что содержат
***или---) создаются с завершающей новой строкой. Это полезно для того, чтобы входные данные, созданные изio.IOBase.readlines(), приводили к различиям, которые подходят для использования сio.IOBase.writelines(), поскольку как входные, так и выходные данные имеют завершающие новые строки.Для входных данных, которые не содержат завершающих символов новой строки, установите для аргумента lineterm значение
"", чтобы выходные данные были равномерно свободны от новой строки.Формат контекстных различий обычно содержит заголовок для имен файлов и времени изменения. Любой из них или все они могут быть указаны с помощью строк для fromfile, tofile, fromfiledate и tofiledate. Время внесения изменений обычно указывается в формате ISO 8601. Если это не указано, то строки по умолчанию будут пустыми.
>>> import sys >>> from difflib import * >>> s1 = ['bacon\n', 'eggs\n', 'ham\n', 'guido\n'] >>> s2 = ['python\n', 'eggy\n', 'hamster\n', 'guido\n'] >>> sys.stdout.writelines(context_diff(s1, s2, fromfile='before.py', ... tofile='after.py')) *** before.py --- after.py *************** *** 1,4 **** ! bacon ! eggs ! ham guido --- 1,4 ---- ! python ! eggy ! hamster guido
Более подробный пример приведен в разделе Интерфейс командной строки для difflib.
- difflib.get_close_matches(word, possibilities, n=3, cutoff=0.6)¶
Возвращает список наилучших, «достаточно хороших» совпадений. word - это последовательность, для которой требуются близкие совпадения (обычно это строка), а possibilities - это список последовательностей, с которыми требуется сопоставить word (обычно это список строк).
Необязательный аргумент n (по умолчанию
3) - это максимальное количество возвращаемых совпадений; n должно быть больше, чем0.Необязательный аргумент cutoff (по умолчанию
0.6) - это значение с плавающей запятой в диапазоне [0, 1]. Варианты, которые не соответствуют параметру word, игнорируются.Наилучшие (не более n) совпадения среди возможных вариантов отображаются в виде списка, отсортированного по степени сходства, сначала выбирается наиболее похожий.
>>> get_close_matches('appel', ['ape', 'apple', 'peach', 'puppy']) ['apple', 'ape'] >>> import keyword >>> get_close_matches('wheel', keyword.kwlist) ['while'] >>> get_close_matches('pineapple', keyword.kwlist) [] >>> get_close_matches('accept', keyword.kwlist) ['except']
- difflib.ndiff(a, b, linejunk=None, charjunk=IS_CHARACTER_JUNK)¶
Сравните a и b (списки строк); верните дельту в стиле
Differ(a generator генерирует дельта-строки).Необязательные параметры ключевых слов linejunk и charjunk являются функциями фильтрации (или
None):linejunk: Функция, которая принимает единственный строковый аргумент и возвращает значение true, если строка является ненужной, или значение false, если нет. Значение по умолчанию
None. Существует также функция на уровне модуляIS_LINE_JUNK(), которая отфильтровывает строки без видимых символов, за исключением не более одного символа-фунта ('#') – однако базовый классSequenceMatcherвыполняет динамический анализ того, какие строки являются настолько часто, что возникает шум, и это обычно работает лучше, чем при использовании данной функции.charjunk: функция, которая принимает символ (строку длиной 1) и возвращает, если символ является ненужным, или false, если нет. По умолчанию используется функция на уровне модуля
IS_CHARACTER_JUNK(), которая отфильтровывает пробельные символы (пробел или табуляция; включать в нее новую строку - плохая идея!).Tools/scripts/ndiff.py- это интерфейс командной строки для этой функции.>>> diff = ndiff('one\ntwo\nthree\n'.splitlines(keepends=True), ... 'ore\ntree\nemu\n'.splitlines(keepends=True)) >>> print(''.join(diff), end="") - one ? ^ + ore ? ^ - two - three ? - + tree + emu
- difflib.restore(sequence, which)¶
Возвращает одну из двух последовательностей, которые сгенерировали дельту.
Учитывая последовательность , полученную с помощью :meth:`Differ.compare` или :func:`ndiff`, извлеките строки, исходящие из файла 1 или 2 (параметр *which), удалив префиксы строк.
Пример:
>>> diff = ndiff('one\ntwo\nthree\n'.splitlines(keepends=True), ... 'ore\ntree\nemu\n'.splitlines(keepends=True)) >>> diff = list(diff) # materialize the generated delta into a list >>> print(''.join(restore(diff, 1)), end="") one two three >>> print(''.join(restore(diff, 2)), end="") ore tree emu
- difflib.unified_diff(a, b, fromfile='', tofile='', fromfiledate='', tofiledate='', n=3, lineterm='\n')¶
Сравните a и b (списки строк); верните дельту (a generator, генерирующую дельта-строки) в унифицированном формате diff.
Унифицированные различия - это компактный способ отображения только тех строк, которые были изменены, плюс несколько строк контекста. Изменения отображаются в виде встроенного текста (вместо отдельных блоков «до» и «после»). Количество строк контекста задается значением n, которое по умолчанию равно трем.
По умолчанию управляющие строки diff (те, что содержат
---,+++, или@@) создаются с завершающей новой строкой. Это полезно для того, чтобы входные данные, созданные изio.IOBase.readlines(), приводили к различиям, которые подходят для использования сio.IOBase.writelines(), поскольку как входные, так и выходные данные имеют завершающие новые строки.Для входных данных, которые не содержат завершающих символов новой строки, установите для аргумента lineterm значение
"", чтобы выходные данные были равномерно свободны от новой строки.Унифицированный формат diff обычно содержит заголовок для имен файлов и времени изменения. Любой из них или все они могут быть указаны с помощью строк для fromfile, tofile, fromfiledate и tofiledate. Время внесения изменений обычно указывается в формате ISO 8601. Если это не указано, то строки по умолчанию будут пустыми.
>>> s1 = ['bacon\n', 'eggs\n', 'ham\n', 'guido\n'] >>> s2 = ['python\n', 'eggy\n', 'hamster\n', 'guido\n'] >>> sys.stdout.writelines(unified_diff(s1, s2, fromfile='before.py', tofile='after.py')) --- before.py +++ after.py @@ -1,4 +1,4 @@ -bacon -eggs -ham +python +eggy +hamster guido
Более подробный пример приведен в разделе Интерфейс командной строки для difflib.
- difflib.diff_bytes(dfunc, a, b, fromfile=b'', tofile=b'', fromfiledate=b'', tofiledate=b'', n=3, lineterm=b'\n')¶
Сравните a и b (списки объектов bytes), используя dfunc; получите последовательность дельта-строк (также байтов) в формате, возвращаемом dfunc. dfunc должен быть вызываемым, обычно либо
unified_diff(), либоcontext_diff().Позволяет сравнивать данные с неизвестной или несогласованной кодировкой. Все входные данные, кроме n, должны быть объектами bytes, а не str. Работает путем преобразования всех входных данных (кроме n) в str без потерь и вызова
dfunc(a, b, fromfile, tofile, fromfiledate, tofiledate, n, lineterm). Выходные данные dfunc затем преобразуются обратно в байты, поэтому получаемые вами дельта-строки имеют те же неизвестные/несогласованные кодировки, что и a и b.Добавлено в версии 3.5.
- difflib.IS_LINE_JUNK(line)¶
Возвращает
Trueдля игнорируемых строк. Строка line игнорируется, если line пуста или содержит один'#', в противном случае она не игнорируется. Используется по умолчанию для параметра linejunk вndiff()в более старых версиях.
- difflib.IS_CHARACTER_JUNK(ch)¶
Возвращает
Trueдля игнорируемых символов. Символ ch игнорируется, если ch является пробелом или символом табуляции, в противном случае он не игнорируется. Используется по умолчанию для параметра charjunk вndiff().
См.также
- Pattern Matching: The Gestalt Approach
Обсуждение аналогичного алгоритма Джоном У. Рэтклиффом и Д. Э. Метцнером. Это было опубликовано в Dr. Dobb’s Journal в июле 1988 года.
Объекты SequenceMatcher¶
В классе SequenceMatcher есть этот конструктор:
- class difflib.SequenceMatcher(isjunk=None, a='', b='', autojunk=True)¶
Необязательный аргумент isjunk должен быть
None(по умолчанию) или функция с одним аргументом, которая принимает элемент последовательности и возвращает значение true тогда и только тогда, когда элемент является «ненужным» и должен игнорироваться. ПередачаNoneдля isjunk эквивалентна передачеlambda x: False; другими словами, никакие элементы не игнорируются. Например, передача:lambda x: x in " \t"
если вы сравниваете строки как последовательности символов и не хотите синхронизировать их с пробелами или жесткими табуляциями.
Необязательные аргументы a и b являются сравниваемыми последовательностями; по умолчанию используются пустые строки. Элементы обеих последовательностей должны быть hashable.
Необязательный аргумент autojunk можно использовать для отключения автоматической эвристики нежелательной почты.
Изменено в версии 3.2: Добавлен параметр автозапуск.
Объекты SequenceMatcher получают три атрибута данных: bjunk - это набор элементов из b, для которых isjunk равен
True; bpopular - это набор не мусорных элементов, которые эвристика считает популярными (если она не отключена); b2j это dict, отображающий остальные элементы b в список позиций, в которых они встречаются. Все три параметра сбрасываются всякий раз, когда b сбрасывается с помощьюset_seqs()илиset_seq2().Добавлено в версии 3.2: Атрибуты bjunk и bpopular.
SequenceMatcherобъекты имеют следующие методы:- set_seqs(a, b)¶
Установите две последовательности для сравнения.
SequenceMatcherвычисляет и кэширует подробную информацию о второй последовательности, поэтому, если вы хотите сравнить одну последовательность со многими последовательностями, используйтеset_seq2()для однократного задания часто используемой последовательности и повторно вызывайтеset_seq1(), по одному разу для каждой из следующих последовательностей. другие последовательности.- set_seq1(a)¶
Установите первую последовательность для сравнения. Вторая последовательность для сравнения не изменяется.
- set_seq2(b)¶
Установите вторую последовательность для сравнения. Первая последовательность для сравнения не изменяется.
- find_longest_match(alo=0, ahi=None, blo=0, bhi=None)¶
Найдите самый длинный совпадающий блок в
a[alo:ahi]иb[blo:bhi].Если значение isjunk было опущено или
None,find_longest_match()возвращает(i, j, k)таким образом, чтоa[i:i+k]равноb[j:j+k], гдеalo <= i <= i+k <= ahiиblo <= j <= j+k <= bhi. Для всех(i', j', k'), удовлетворяющих этим условиям, также выполняются дополнительные условияk >= k',i <= i', и еслиi == i',j <= j'. Другими словами, из всех максимально совпадающих блоков верните тот, который начинается раньше всего в a, а из всех максимально совпадающих блоков, которые начинаются раньше всего в a, верните тот, который начинается раньше всего в b.>>> s = SequenceMatcher(None, " abcd", "abcd abcd") >>> s.find_longest_match(0, 5, 0, 9) Match(a=0, b=4, size=5)
Если было указано значение isjunk, сначала определяется самый длинный соответствующий блок, как указано выше, но с дополнительным ограничением, чтобы в блоке не было ненужных элементов. Затем этот блок расширяется, насколько это возможно, путем сопоставления (только) ненужных элементов с обеих сторон. Таким образом, результирующий блок никогда не совпадает с мусором, за исключением случаев, когда идентичный мусор оказывается рядом с интересным совпадением.
Вот тот же пример, что и раньше, но с учетом того, что пробелы считаются ненужными. Это не позволяет
' abcd'напрямую соответствовать' abcd'в конце второй последовательности. Вместо этого может совпадать только'abcd', который совпадает с крайним левым'abcd'во второй последовательности:>>> s = SequenceMatcher(lambda x: x==" ", " abcd", "abcd abcd") >>> s.find_longest_match(0, 5, 0, 9) Match(a=1, b=0, size=4)
Если ни один из блоков не совпадает, то возвращается
(alo, blo, 0).Этот метод возвращает named tuple
Match(a, b, size).Изменено в версии 3.9: Добавлены аргументы по умолчанию.
- get_matching_blocks()¶
Возвращает список троек, описывающих непересекающиеся совпадающие подпоследовательности. Каждая тройка имеет вид
(i, j, n)и означает, чтоa[i:i+n] == b[j:j+n]. Тройки монотонно увеличиваются в i и j.Последняя тройка является фиктивной и имеет значение
(len(a), len(b), 0). Это единственная тройка сn == 0. Если(i, j, n)и(i', j', n')являются соседними тройками в списке, а вторая тройка не является последней в списке, тоi+n < i'илиj+n < j'; другими словами, соседние тройки всегда описывают несмежные равные блоки.>>> s = SequenceMatcher(None, "abxcd", "abcd") >>> s.get_matching_blocks() [Match(a=0, b=0, size=2), Match(a=3, b=2, size=2), Match(a=5, b=4, size=0)]
- get_opcodes()¶
Возвращает список из 5 кортежей, описывающих, как превратить a в b. Каждый кортеж имеет вид
(tag, i1, i2, j1, j2). Первый кортеж имеет значениеi1 == j1 == 0, а остальные кортежи имеют значение i1, равное i2 из предыдущего кортежа, и, аналогично, j1, равное предыдущему j2.Значения tag представляют собой строки со следующими значениями:
Ценность
Значение
'replace'a[i1:i2]следует заменить наb[j1:j2].'delete'a[i1:i2]должно быть удалено. Обратите внимание, что в этом случаеj1 == j2.'insert'b[j1:j2]должно быть вставлено вa[i1:i1]. Обратите внимание, что в этом случаеi1 == i2.'equal'a[i1:i2] == b[j1:j2](подпоследовательности равны).Например:
>>> a = "qabxcd" >>> b = "abycdf" >>> s = SequenceMatcher(None, a, b) >>> for tag, i1, i2, j1, j2 in s.get_opcodes(): ... print('{:7} a[{}:{}] --> b[{}:{}] {!r:>8} --> {!r}'.format( ... tag, i1, i2, j1, j2, a[i1:i2], b[j1:j2])) delete a[0:1] --> b[0:0] 'q' --> '' equal a[1:3] --> b[0:2] 'ab' --> 'ab' replace a[3:4] --> b[2:3] 'x' --> 'y' equal a[4:6] --> b[3:5] 'cd' --> 'cd' insert a[6:6] --> b[5:6] '' --> 'f'
- get_grouped_opcodes(n=3)¶
Возвращает generator групп, содержащих до n строк контекста.
Начиная с групп, возвращаемых с помощью
get_opcodes(), этот метод разбивает меньшие кластеры изменений и устраняет промежуточные диапазоны, в которых изменений нет.Группы возвращаются в том же формате, что и
get_opcodes().
- ratio()¶
Возвращает меру сходства последовательностей в виде числа с плавающей точкой в диапазоне [0, 1].
Где T - общее количество элементов в обеих последовательностях, а M - количество совпадений, это 2,0*M / T. Обратите внимание, что это
1.0, если последовательности идентичны, и0.0, если у них нет ничего общего.Это дорогостоящее вычисление, если
get_matching_blocks()илиget_opcodes()еще не были вызваны, и в этом случае вы можете сначала попробоватьquick_ratio()илиreal_quick_ratio(), чтобы получить верхнюю границу.Примечание
Внимание: Результат вызова
ratio()может зависеть от порядка аргументов. Например:>>> SequenceMatcher(None, 'tide', 'diet').ratio() 0.25 >>> SequenceMatcher(None, 'diet', 'tide').ratio() 0.5
Три метода, которые возвращают отношение совпадения к общему количеству символов, могут давать разные результаты из-за различных уровней аппроксимации, хотя quick_ratio() и real_quick_ratio() всегда по меньшей мере равны ratio():
>>> s = SequenceMatcher(None, "abcd", "bcde")
>>> s.ratio()
0.75
>>> s.quick_ratio()
0.75
>>> s.real_quick_ratio()
1.0
Примеры последовательностей¶
В этом примере сравниваются две строки, в которых пробелы считаются «ненужными».:
>>> s = SequenceMatcher(lambda x: x == " ",
... "private Thread currentThread;",
... "private volatile Thread currentThread;")
ratio() возвращает значение с плавающей точкой в [0, 1], измеряющее сходство последовательностей. Как правило, значение ratio() больше 0,6 означает, что последовательности почти совпадают:
>>> print(round(s.ratio(), 3))
0.866
Если вас интересует только совпадение последовательностей, get_matching_blocks() будет удобно:
>>> for block in s.get_matching_blocks():
... print("a[%d] and b[%d] match for %d elements" % block)
a[0] and b[0] match for 8 elements
a[8] and b[17] match for 21 elements
a[29] and b[38] match for 0 elements
Обратите внимание, что последний кортеж, возвращаемый get_matching_blocks(), всегда является фиктивным, (len(a), len(b), 0), и это единственный случай, когда последний элемент кортежа (количество совпадающих элементов) равен 0.
Если вы хотите знать, как изменить первую последовательность на вторую, используйте get_opcodes():
>>> for opcode in s.get_opcodes():
... print("%6s a[%d:%d] b[%d:%d]" % opcode)
equal a[0:8] b[0:8]
insert a[8:8] b[8:17]
equal a[8:29] b[17:38]
См.также
Функция
get_close_matches()в этом модуле, которая показывает, как простой код, основанный наSequenceMatcher, может быть использован для выполнения полезной работы.Simple version control recipe для небольшого приложения, созданного с помощью
SequenceMatcher.
Разные объекты¶
Обратите внимание, что Differ-сгенерированные значения delta не претендуют на то, чтобы быть минимальными различиями. Напротив, минимальные различия часто противоречат интуиции, потому что они синхронизируются везде, где это возможно, иногда случайно совпадают с интервалом в 100 страниц. Ограничение точек синхронизации смежными совпадениями сохраняет некоторое представление о локальности, но иногда приводит к увеличению размера различий.
В классе Differ есть этот конструктор:
- class difflib.Differ(linejunk=None, charjunk=None)
Необязательные параметры ключевых слов linejunk и charjunk предназначены для функций фильтрации (или
None):linejunk: Функция, которая принимает единственный строковый аргумент и возвращает значение true, если строка является ненужной. Значение по умолчанию
None, что означает, что ни одна строка не считается ненужной.charjunk: функция, которая принимает односимвольный аргумент (строку длиной 1) и возвращает значение true, если символ является ненужным. Значение по умолчанию
None, что означает, что ни один символ не считается ненужным.Эти функции фильтрации нежелательной почты ускоряют поиск различий и не приводят к игнорированию каких-либо отличающихся строк или символов. Для получения более подробной информации ознакомьтесь с описанием параметра isjunk для метода
find_longest_match().Differобъекты используются (генерируются дельты) с помощью одного метода:- compare(a, b)¶
Сравните две последовательности линий и сгенерируйте дельту (последовательность линий).
Каждая последовательность должна содержать отдельные однострочные строки, заканчивающиеся символами новой строки. Такие последовательности могут быть получены с помощью метода
readlines()для файлоподобных объектов. Сгенерированная разность также состоит из строк, заканчивающихся новой строкой, готовых к печати как есть с помощью методаwritelines()объекта, подобного файлу.
Другой пример¶
В этом примере сравниваются два текста. Сначала мы настраиваем тексты - последовательности отдельных однострочных строк, заканчивающихся символами новой строки (такие последовательности также можно получить с помощью метода readlines() для файлоподобных объектов).:
>>> text1 = ''' 1. Beautiful is better than ugly.
... 2. Explicit is better than implicit.
... 3. Simple is better than complex.
... 4. Complex is better than complicated.
... '''.splitlines(keepends=True)
>>> len(text1)
4
>>> text1[0][-1]
'\n'
>>> text2 = ''' 1. Beautiful is better than ugly.
... 3. Simple is better than complex.
... 4. Complicated is better than complex.
... 5. Flat is better than nested.
... '''.splitlines(keepends=True)
Затем мы создаем экземпляр объекта Different:
>>> d = Differ()
Обратите внимание, что при создании экземпляра объекта Differ мы можем передавать функции для фильтрации «ненужных» строк и символов. Подробности смотрите в конструкторе Differ().
Наконец, мы сравниваем эти два:
>>> result = list(d.compare(text1, text2))
result - это список строк, так что давайте оформим его красиво:
>>> from pprint import pprint
>>> pprint(result)
[' 1. Beautiful is better than ugly.\n',
'- 2. Explicit is better than implicit.\n',
'- 3. Simple is better than complex.\n',
'+ 3. Simple is better than complex.\n',
'? ++\n',
'- 4. Complex is better than complicated.\n',
'? ^ ---- ^\n',
'+ 4. Complicated is better than complex.\n',
'? ++++ ^ ^\n',
'+ 5. Flat is better than nested.\n']
В виде одной многострочной строки это выглядит следующим образом:
>>> import sys
>>> sys.stdout.writelines(result)
1. Beautiful is better than ugly.
- 2. Explicit is better than implicit.
- 3. Simple is better than complex.
+ 3. Simple is better than complex.
? ++
- 4. Complex is better than complicated.
? ^ ---- ^
+ 4. Complicated is better than complex.
? ++++ ^ ^
+ 5. Flat is better than nested.
Интерфейс командной строки для difflib¶
В этом примере показано, как использовать difflib для создания утилиты, подобной diff. Она также содержится в исходном коде Python как Tools/scripts/diff.py.