简介 Difflib 是 Python 编程语言中的一个内置模块,帮助我们进行差异化比较。
它能够生成文本或者 html 格式的差异化比较结果,如果需要比较目录的不同,可以使用 filecmp 模块。
Python Difflib 模块中最常用的类是 Differ 和 Sequence Matcher 类。还有一些其他辅助类和函数,可以用于更特定的操作。
class difflib.SequenceMatcher
Sequence Matcher 比较两个提供的字符串,并返回表示两个字符串之间相似性的数据。
可以用来比较任何类型片段的类,只要比较的片段是可 hash 的。他源于1980,s的“完形匹配算法”,并且进行了一系列的优化和改进。它由于原始的完形匹配算法,在最坏情况下有n的平方次运算,在最好情况下,具有线性的效率。
它具有自动垃圾启发式,可以将重复超过片段 1% 或者重复 200 次的字符作为垃圾来处理。可以通过将 autojunk 设置为 false 关闭该功能。
autojunk 参数新增于2.7.1版本。
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 import difflib from difflib import SequenceMatcher str_1 = "Welcome to javatiku" str_2 = "Welcome to Python tutorial" my_seq = SequenceMatcher(a = str_1, b = str_2) print("Sequence Matched:" , my_seq.ratio())
class difflib.Differ
Differ 被认为是 SequenceMatcher 的反义词。它接受文本行并查找字符串之间的差异。但 Differ 类在使用增量时特殊之处,使其更有效且对人类更可读,以便发现差异。
例如,在比较两个字符串之间插入新字符时,在接收额外字符的行之前会出现’ + ‘。它用以下符号来表示不同
Code
Meaning
‘- ‘
仅在片段1中存在
‘+ ‘
仅在片段2中存在
‘ ‘
片段1和2中都存在
‘? ‘
存在疑问的
标识为?需要你通过人工的方式仔细比较他们的不同,他们产生的原因是源于混乱的制表符
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import difflib from difflib import Differ str_1 = "They would like to order a soft drink" str_2 = "They would like to order a corn pizza" lines_str1 = str_1.splitlines() lines_str2 = str_2.splitlines() dif = difflib.Differ() my_diff = dif.compare(lines_str1, lines_str2) print("Difference between the Strings" ) print('\n' .join(my_diff))
输出
1 2 3 4 5 - They would like to order a soft drink ? ^ ^^ ^^ ^^ + They would like to order a corn pizza ?
class difflib.HtmlDiff
这个类用来创建一个html表格(或者包含html表格的文件)用来展示文件差异。他既可以进行全文本展示,也可以只展示上下文不同。
这个类的构造函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 __init__ (tabsize=8, wrapcolumn=None, linejunk=None, charjunk=IS_CHARACTER_ JUNK) tabsize表示制表符代表的空格个数,默认为8 wrapcolumn,可选参数,用来设置多少个字符时自动换行,默认None,为None时表示不自动换行 linejunk 和 charjunk,可选参数,在ndiff()中使用 这个类的公共方法: make_file(fromlines, tolines [, fromdesc ][, todesc ][, context ][, numlines ]) 用来生成一个包含表格的html文件,其内容是用来展示差异。 fromlines 和tolines,用于比较的内容,格式为字符串组成的列表 fromdesc 和 todesc,可选参数,对应的fromlines,tolines的差异化文件的标题,默认为空字符串 context 和 numlines,可选参数,context 为True时,只显示差异的上下文,为false,显示全文,numlines默认为5,当context为True时,控制展示上下文的行数,当context为false时,控制不同差异的高亮之间移动时“next”的开始位置(如果设置为0,当移动懂顶端时,超链接会丢失引用地址) make_table(fromlines, tolines [, fromdesc ][, todesc ][, context ][, numlines ]) 这个方法和make_file用法一样,唯一的区别在于它只生成了一个html表格字符串
python 安装包的 Tools/scripts/diff.py 是关于他们使用的一个很好的例子,它可以用命令行来运行。
get_close_matches
接受参数并返回与目标字符串最接近的匹配项。
语法:
1 2 3 4 5 6 get_close_matches(target_word , list_of_possibilities , n = res_limit , cutoff ) 第一个参数是要定位的单词;我们希望方法返回相似性。 第二个参数可以是变量或指向字符串数组的变量的数组。 第三个参数允许用户定义要返回的输出数量的限制。 最后一个参数确定两个单词之间的相似度需要多大才能作为输出返回。
仅使用前两个参数,函数将根据默认切割值0.6(在0 - 1范围内)和默认结果限制3返回输出。
示例:
1 2 3 4 5 6 7 8 9 import difflib from difflib import get_close_matches my_list = get_close_matches('mas' , ['master' , 'mask' , 'duck' , 'cow' , 'mass' , 'massive' , 'python' , 'butter' ]) print("Matching words:" , my_list)
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import difflib from difflib import get_close_matches my_list = get_close_matches( 'mas' , ['master' , 'mask' , 'duck' , 'cow' , 'mass' , 'massive' , 'python' , 'butter' ], n = 4 , cutoff = 0.6 ) print("Matching words:" , my_list)
unified_diff
和 context_diff
在 difflib 中有两个类,它们的工作方式相同:unified_diff
和 context_diff
。它们之间的唯一主要区别是结果。
context_diff
类接受两个数据字符串,然后返回从第一个字符串中插入或删除的每个单词。
示例:
1 2 3 4 5 6 7 8 9 10 11 import sys import difflib from difflib import unified_diff str_1 = ['Mark\n' , 'Henry\n' , 'Richard\n' , 'Stella\n' , 'Robin\n' , 'Employees\n' ] str_2 = ['Arthur\n' , 'Joseph\n' , 'Stacey\n' , 'Harry\n' , 'Emma\n' , 'Employees\n' ] sys.stdout.writelines(unified_diff(str_1, str_2))
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 @@ -1,6 +1,6 @@ -Mark -Henry -Richard -Stella -Robin +Arthur +Joseph +Stacey +Harry +Emma Employees
我们可以观察到 unified_diff
返回被删除的单词前缀为-
,返回添加的单词前缀为+
。最后一个单词”Employees”在两个字符串中都没有前缀。
context_diff
类的工作方式与 unified_diff
类似。但是,它不是显示原始字符串中插入和删除了什么,而是通过返回带有 !
前缀的已更改行来表示哪些行发生了更改。
示例:
1 2 3 4 5 6 7 8 9 10 11 import sys import difflib from difflib import context_diff str_1 = ['Mark\n' , 'Henry\n' , 'Richard\n' , 'Stella\n' , 'Robin\n' , 'Employees\n' ] str_2 = ['Arthur\n' , 'Joseph\n' , 'Stacey\n' , 'Harry\n' , 'Emma\n' , 'Employees\n' ] sys.stdout.writelines(context_diff(str_1, str_2))
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 *** --- *************** *** 1,6 **** ! Mark ! Henry ! Richard ! Stella ! Robin Employees --- 1,6 ---- ! Arthur ! Joseph ! Stacey ! Harry ! Emma Employees
difflib.ndiff
比较a与b(字符串列表),返回一个Differ-style 的差异结果
1 2 3 4 5 difflib.ndiff(a, b[, linejunk ][, charjunk ]) linejunk和charjunk都是用来匹配的方法 linejunk:接收一个字符串的方法,如果这个字符串被认定为垃圾,则返回 true,否则为 false,默认为None,他调用了IS_LINE_JUNK() 这个方法,这个方法存在 bug,他不能过滤掉’#’周围的不可见字符,2.3以后,对这个方法进行了动态分析,表现会比以前好些 charjunk:接受一个字符的方法,如果这个字符被认定为垃圾,则返回 true,否则为 false,它调用了 IS_CHARACTER_JUNK(), 他会自动过滤掉空白字符(所以,不要用空白字符或者制表符作为分隔符)
difflib.restore
返回一个由两个比对序列产生的结果
1 difflib.restore (sequence, which )
Reference