کتابخانه difflib یکی از ماژولهای استاندارد و قدرتمند پایتون است که برای مقایسه توالیها (Sequences) مانند رشتههای متنی، لیستها و فایلها استفاده میشود. اگر تا به حال خواستهاید سیستمی بسازید که "آیا منظور شما این بود؟" (Did you mean) را پیادهسازی کند یا تفاوت بین دو فایل متنی را پیدا کند، difflib ابزار شماست.
در این مقاله، از مفاهیم اولیه مانند پیدا کردن کلمات مشابه شروع کرده و تا تولید گزارشهای حرفهای HTML و تحلیل دقیق Opcodes پیش میرویم.

سطح مقدماتی (Beginner Level)
در این بخش با توابع کلیدی و پرکاربرد difflib که برای کارهای روزمره و ساده مناسب هستند آشنا میشویم.
۱. پیدا کردن موارد مشابه (get_close_matches)
یکی از محبوبترین توابع این ماژول get_close_matches است. این تابع به شما کمک میکند تا نزدیکترین رشتهها به یک رشته خاص را از بین یک لیست پیدا کنید. این اساس کار سیستمهای اصلاح غلط املایی است.
مثال اول: اصلاح غلط املایی ساده
فرض کنید کاربر کلمه "appel" را وارد کرده و ما میخواهیم حدس بزنیم منظورش چه بوده است.
مثال دوم: تنظیم حساسیت و تعداد نتایج
شما میتوانید با پارامترهای n (تعداد نتایج) و cutoff (حداقل درصد شباهت بین ۰ تا ۱) نتایج را فیلتر کنید.
۲. محاسبه درصد شباهت (SequenceMatcher)
کلاس SequenceMatcher قلب تپنده این ماژول است. این کلاس میتواند دو توالی را مقایسه کرده و یک عدد بین 0.0 (کاملا متفاوت) تا 1.0 (کاملا یکسان) به عنوان نسبت شباهت برگرداند.
مثال اول: شباهت دو رشته متنی
مثال دوم: مقایسه لیست اعداد
difflib فقط مختص متن نیست؛ هر نوع توالی (Sequence) قابل هش (Hashable) را مقایسه میکند.
۳. نمایش تفاوتها به صورت خط به خط (Differ)
کلاس Differ برای تولید تفاوتها به صورتی که برای انسان خوانا باشد (Human-readable) استفاده میشود. خروجی شبیه به دستور diff در لینوکس است.
-: خطی که در متن اول بوده ولی در دوم نیست.+: خطی که در متن دوم اضافه شده است.: خطی که در هر دو مشترک است.
مثال اول: مقایسه متن چند خطی
مثال دوم: مقایسه درون خطی (Intraline diff)
کلاس Differ گاهی اوقات کاراکتر ^ را نشان میدهد تا دقیقاً مشخص کند تغییر در کجای خط رخ داده است.
سطح پیشرفته (Professional Level)
در این بخش به سراغ تولید گزارشهای استاندارد، خروجی HTML برای وبسایتها، و درک عمیق الگوریتمهای تطبیق (Matching Algorithms) میرویم.
۱. تولید گزارش تفاوت HTML (HtmlDiff)
برای نمایش تفاوتها در وبسایت یا داشبوردهای مدیریتی، بهترین گزینه HtmlDiff است. این کلاس یک جدول کامل HTML شامل رنگبندی تفاوتها تولید میکند.
مثال اول: ساخت جدول مقایسه کامل
مثال دوم: شخصیسازی جدول HTML
شما میتوانید تبها را به فاصله تبدیل کنید یا از حالت در ابزارهای کنترل نسخه (مانند Git) یا پچ کردن فایلها، فرمتهای خاصی استاندارد هستند. این فرمت بسیار محبوب است و فقط خطوط تغییر یافته به همراه چند خط زمینه (Context) را نشان میدهد. این فرمت قدیمیتر است و دو فایل را جداگانه با علامتگذاری تغییرات نشان میدهد. اگر نیاز دارید دقیقاً بدانید چه عملیاتی (حذف، درج، جایگزینی) باید انجام شود تا لیست A به لیست B تبدیل شود، باید از متد خروجی این متد شامل تاپلهایی به فرمت متد در مقایسه فایلهای کد منبع، گاهی اوقات میخواهیم فاصلههای خالی (Whitespace) یا خطوط خالی را نادیده بگیریم. پارامتر اول در این مثال، اگر فاصله را نادیده نگیریم، رشتهها متفاوتند، اما با نادیده گرفتن فاصله، الگوریتم رفتار متفاوتی در محاسبه بلوکها نشان میدهد (هرچند زمانی که لیستهای بسیار بزرگ را مقایسه میکنید، اگر عنصری بیش از ۱٪ کل لیست تکرار شده باشد، make_table برای گرفتن فقط تگ (بدون
و کامل) استفاده کنید تا آن را در قالب سایت خود قرار دهید.
# Static Snippet: Function signature for customization
# این کد استاتیک است چون فقط نشاندهنده نحوه فراخوانی متد است
html_diff = difflib.HtmlDiff(tabsize=4, wrapcolumn=60)
table_only = html_diff.make_table(lines1, lines2)۲. فرمتهای استاندارد Unified و Context Diff
difflib این فرمتها را پشتیبانی میکند.مثال اول: Unified Diff (فرمت فشرده)
مثال دوم: Context Diff
۳. تحلیل عمیق با Opcodes
get_opcodes() در SequenceMatcher استفاده کنید.(tag, i1, i2, j1, j2) است:
replace: a[i1:i2] باید با b[j1:j2] جایگزین شود.delete: a[i1:i2] باید حذف شود.insert: b[j1:j2] باید در موقعیت i1 در a درج شود.equal: این بخشها یکسان هستند.مثال اول: استخراج عملیات تغییر
مثال دوم: پیدا کردن طولانیترین بخش مشترک
find_longest_match برای پیدا کردن بزرگترین زیررشته مشترک استفاده میشود که در الگوریتمهای فشردهسازی متن کاربرد دارد.۴. فیلتر کردن نویزها (Junk Elements)
SequenceMatcher (که معمولا None است) تابعی است که مشخص میکند چه کاراکترهایی "Junk" هستند.مثال اول: نادیده گرفتن فاصلهها
ratio() کلی تغییر چندانی نمیکند، اما نحوه تطبیق بلوکها عوض میشود). الگوریتم difflib به این صورت است که Junkها را در تطبیق بلوکها شرکت نمیدهد.مثال دوم: بهینهسازی سرعت با autojunk
difflib به صورت خودکار آن را نادیده میگیرد تا سرعت بالا رود. میتوانید با autojunk=False این قابلیت را خاموش کنید.# Static: نمایش پارامتر در سازنده
# استفاده از autojunk برای لیستهای بزرگ توصیه میشود
matcher = difflib.SequenceMatcher(None, large_list_a, large_list_b, autojunk=True)