您的位置:

Python 中的difflib模块

在下面的教程中,我们将了解 Python 编程语言中的 difflib模块。我们将讨论这个模块的功能以及一些基于它的类的例子。

所以,让我们开始吧。

理解 Python difflib模块

Difflib 是 Python 编程语言中的内置模块,由不同的简单函数和类组成,允许用户比较数据集。该模块以人类可以阅读的格式提供这些序列比较的输出,使用差值来更有效地显示差异。

difflib模块通常用于比较字符串的顺序。但是我们也可以用它来比较其他数据类型,只要它们是可哈希的。我们知道,如果一个对象的哈希值在它的生命周期内没有改变,那么它就是可哈希的。

Python difflib模块中最常用的类是 different 类和序列匹配器类。还有一些其他的帮助类和函数可以帮助更特殊的操作。让我们在接下来的章节中了解其中的一些功能。

理解序列匹配器类

让我们首先从 difflib模块的一个相当不言自明的方法开始: SequenceMatcher 。SequenceMatcher 方法将比较两个提供的字符串,并返回表示两个字符串之间相似性的数据。让我们借助比()对象来试试这个方法。该对象将以十进制格式返回比较数据。相同的示例如下所示:

示例:


# importing the difflib library and SequenceMatcher class
import difflib
from difflib import SequenceMatcher

# defining the strings
str_1 = "Welcome to Javatpoint"
str_2 = "Welcome to Python tutorial"

# using the SequenceMatcher() function
my_seq = SequenceMatcher(a = str_1, b = str_2)

# printing the result
print("First String:", str_1)
print("Second String:", str_2)
print("Sequence Matched:", my_seq.ratio())

输出:

First String: Welcome to Javatpoint
Second String: Welcome to Python tutorial
Sequence Matched: 0.5106382978723404

说明:

在上面的代码片段中,我们首先导入了 difflib 模块以及 SequenceMatcher 类。然后我们定义了两个字符串值,我们将在该类的帮助下进行比较。之后,我们创建了一个新的变量,它用两个参数封装了 SequenceMatcher 类,分别是 a 和 b 。而该方法实际上接受三个参数:无,a ,b。

为了让方法确认这两个字符串,我们必须将字符串的每个值分配给方法的变量, SquenceMatcher(a = str_1,b = str_2)** 。

一旦定义了每个需要的变量,并且序列匹配器至少提供了两个参数,我们现在就可以借助于前面提到的比率()对象来打印该值。该对象将确定两个字符串中相同字符的比例,输出以十进制形式返回。就像这样,我们比较了两个简单的字符串,并收到了关于它们相似性的输出。

注意:ratio()对象是与序列匹配器类相关联的几个对象之一。您可以查看 Python 的官方文档,了解更多这些对象,以便对序列执行不同的操作。

理解不同的类别

different类被认为是 SquenceMatcher 的反义词;它接收文本行并找出字符串之间的差异。但是差异类在三角洲的利用上是特别的,这使得人类发现差异的效率和可读性更高。

例如,当在两个字符串之间的比较中向第二个字符串插入新字符时,在接收到额外字符的行之前会弹出一个“ + ”。

正如我们可能已经猜到的,删除第一个字符串中的一些可见字符将导致第二行文本之前出现“ - ”。

如果两个序列中有一行相同,将返回“,”如果缺少一行,那么“?'会出现。此外,我们还可以使用属性,如比率(),我们在前面的示例中讨论过。

让我们考虑下面的例子来理解不同类的工作原理。

示例:


# importing the difflib module and Differ class
import difflib
from difflib import Differ

# defining the strings
str_1 = "They would like to order a soft drink"
str_2 = "They would like to order a corn pizza"

# using the splitlines() function
lines_str1 = str_1.splitlines()
lines_str2 = str_2.splitlines()

# using the Differ() and compare() function
dif = difflib.Differ()
my_diff = dif.compare(lines_str1, lines_str2)

# printing the results
print("First String:", str_1)
print("Second String:", str_2)
print("Difference between the Strings")
print('\n'.join(my_diff))

输出:

First String: They would like to order a soft drink
Second String: They would like to order a corn pizza
Difference between the Strings
- They would like to order a soft drink
?                            ^ ^^ ^^ ^^

+ They would like to order a corn pizza
?                            ^ ^^ ^ ^^^

说明:

在上面的代码片段中,我们已经导入了 difflib 模块和different类。然后,我们定义了要比较的两个字符串。然后,我们在两个字符串上调用了分裂线()函数。

语法:


lines_str1 = str_1.splitlines()
lines_str2 = str_2.splitlines()

这个函数允许我们按每行而不是按每个字符来比较字符串。

一旦我们定义了一个由different类组成的变量,我们就创建了另一个包含different和 compare() 对象的变量,该对象接受两个字符串作为参数。

语法:


my_diff = dif.compare(lines_str1, lines_str2)

我们调用 print() 函数,并将 my_diff 变量与一行 enter 连接起来,这样输出就可以用一种更易读的方法进行格式化。

理解 get_close_matches 方法

difflib 模块作为 get_close_matches 方法提供了另一个简单而强大的工具。这个方法听起来很像:一个接受参数并返回与目标字符串最接近的匹配的工具。在伪代码中,函数以下列方式运行:

语法:


get_close_matches(target_word, list_of_possibilities, n = res_limit, cutoff)

我们可以观察到上面的语法, get_close_matches() 方法接受四个参数;但是,它只需要第一个两个就可以返回输出。

第一个参数是必须针对的词;我们希望该方法返回相似性。第二个参数可以是指向字符串数组的变量或术语数组。第三个参数允许用户定义返回的输出数量的限制。最后一个参数决定了两个单词之间的相似度需要多少才能作为输出返回。

单用前两个参数,该函数将基于 0.6 (在 0 - 1 范围内)的默认截止值和 3** 的默认结果限制返回输出。让我们考虑下面的例子来理解这个函数的工作原理。

示例:


# importing the difflib module and get_close_matches method
import difflib
from difflib import get_close_matches

# using the get_close_matches method
my_list = get_close_matches('mas', ['master', 'mask', 'duck', 'cow', 'mass', 'massive', 'python', 'butter'])

# printing the list
print("Matching words:", my_list)

输出:

Matching words: ['mass', 'mask', 'master']

说明:

在上面的代码片段中,我们已经导入了 difflib 模块和 get_close_matches 方法。然后,我们使用了 get_close_matches() 方法,列出了一些在性质上有些相似的项目。一旦我们执行该程序,该函数将只返回其中有相似字母的三个单词,即使有第四个项目类似于单词“MAS”:“massive”。现在,让我们尝试在以下示例中定义一个结果限制和一个截止:

示例:


# importing the difflib module and get_close_matches method
import difflib
from difflib import get_close_matches

# using the get_close_matches method
my_list = get_close_matches(
    'mas',
    ['master', 'mask', 'duck', 'cow',
    'mass', 'massive', 'python', 'butter'],
    n = 4,
    cutoff = 0.6
    )

# printing the list
print("Matching words:", my_list)

输出:

Matching words: ['mass', 'mask', 'master', 'massive']

说明:

在上面的代码片段中,我们得到了四个至少与单词“ mas 相似 60% 的结果。截止相当于原来的我们刚刚定义的默认值相同, 0.6 。但是,我们可以更改此参数,使结果或多或少更严格。越靠近 1 ,约束越严格。

理解统一的 _diff & context_diff 类

difflib 中有两个类的工作方式相同: unified_diff 和 context_diff 。两者之间唯一的主要区别是结果。

unified_diff 类接受两个数据字符串,然后返回从第一个字符串插入或删除的每个单词。

为了更好地理解,让我们考虑下面的例子。

示例:


# importing the required modules
import sys
import difflib
from difflib import unified_diff

# defining the string variables
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']

# using the unified_diff() function
sys.stdout.writelines(unified_diff(str_1, str_2))

输出:

--- 
+++ 
@@ -1,6 +1,6 @@
-Mark
-Henry
-Richard
-Stella
-Robin
+Arthur
+Joseph
+Stacey
+Harry
+Emma
 Employees

说明:

在上面的代码片段中,我们已经导入了所需的模块,并定义了两个存储一些单词的变量。然后,我们使用 unified_diff()函数从第一个变量中删除单词,并将第二个变量中的单词添加到第一个变量中。因此,我们可以观察到 unified_diff 返回删除的前缀为 - 的单词,返回添加的前缀为 + 的单词。最后一个单词, Employees ,在两个字符串中都没有前缀。

context_diff 类的工作方式与 unified_diff 相似。但是,它不会显示从原始字符串中插入和删除的内容,而是通过返回前缀为“!”的已更改行来返回已更改的行。

让我们考虑下面的例子来理解这个类的工作。

示例:


# importing the required modules
import sys
import difflib
from difflib import context_diff

# defining the string variables
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']

# using the context_diff() function
sys.stdout.writelines(context_diff(str_1, str_2))

输出:

*** 
--- 
***************
*** 1,6 ****
! Mark
! Henry
! Richard
! Stella
! Robin
  Employees
--- 1,6 ----
! Arthur
! Joseph
! Stacey
! Harry
! Emma
  Employees

说明:

在上面的例子中,我们使用了 context_diff 来移除和添加第一个字符串中的单词。同样的结果可以观察到,因为被改变的单词用“!”来描述前缀。