فرمتینگ مناسب در پایتون

فرمتینگ مناسب در پایتون (تجربه)

همیشه برام دغدغه بود که چه فرمتر (formatter) یا ابزار فرمت‌بندی کد رو برای پروژه‌های پایتون (Python) انتخاب کنم. فرمترها ابزارهایی هستند که کد منبع را مطابق با دستورالعمل‌های استایل خاصی تجزیه و تحلیل و بازنویسی می‌کنند تا خوانایی و یکنواختی کد افزایش پیدا کنه. این ابزارها به ما کمک می‌کنند تا اطمینان حاصل کنیم که کد ما نه تنها درست کار می‌کند، بلکه به زیبایی و به شکل استاندارد نوشته شده. برای پایتون سه تا formatter اصلی وجود داره.همیشه بین این سه گزینه گیر می‌کردم: Black، autopep8، و YAPF. هر بار در پروژه‌های یکی رو انتخاب می‌کردم ولی یه بار رفتم اساسی بررسی کردم اینا چه تفاوتهایی دارن. هر کدوم قابلیت‌ها و ویژگی‌های منحصر به فرد خودشون رو دارند و انتخاب بین این‌ها واقعا سخته. اما بزارید یه نگاه دقیق‌تر به هر کدوم بندازیم:


1. Black

فرمتر Black به شدت خودکار و بی‌طرفانه (opinionated) عمل می‌کنه. این فرمتر با اینکه خیلی سفت و سخته (uncompromising)، ولی به خاطر همین خصوصیتش خیلی هم محبوب شده. نظم خاصی به کد می‌ده و تقریبا هیچ جایی برای بحث و جدل در مورد سبک کدنویسی باقی نمی‌ذاره. ویژگی بارزش بخاطر این سختی‌گیری نسبت به yapf متعین(deterministic) بودنشه یعنی اگر روی یک کد اجرا کنی حتما به یک شکل مشخص در میاره. برای یک کد چند تا حالت مختلف رو به عنوان حالت معتبر از نظر فرمت در نظر نمی‌گیره ولی yapf اینطوری نیست جلوتر توضیح میدم.

یک مشکل بزرگ داره انعطاف‌پذیری کمی داره (less flexible) و شاید برای پروژه‌هایی که نیاز به سبک خاصی دارند مناسب نباشه.


2. autopep8

فرمتر autopep8 دقیقا روی استانداردهای PEP 8 (PEP 8) تمرکز داره. این فرمتر کدها رو به شکلی استاندارد و خوانا (readable) درمیاره ولی فقط مطابق autopep8. کد را آنالیز می‌کند و خطاهای استایل را اصلاح می‌کند تا با استانداردهای PEP 8 همخوانی داشته باشد.

گاهی اوقات نمی‌تونه به اندازه Black یا YAPF انعطاف‌پذیر باشه (not as flexible) و ولی تعداد قوانین‌ش به اندازه‌ی black‌ زیاد نیست.

معنی انعطاف پذیر بودنش اینه که اگر یک کدی با black فرمت شده باشه اینقدر قوانین خیلی سفت و سختی داره (strict rules) که قوانین Autopep هم درش رعایت شده مثلا PEP8 میگه طول خط از 79 بیشتر نشه ولی black میاد اینقدر طول خط رو کوتاه میکنه که از 79 خیلی کمتر و قواعد هر دو تا استاندارد رو پاس میکنه.


3. YAPF

فرمتر YAPF خیلی قابل تنظیم و انعطاف‌پذیره (highly configurable). این فرمتر بر اساس یک پروفایلی که شما تعیین می‌کنید، کد رو فرمت می‌کنه. YAPF کد را بازبینی کرده و بر اساس پروفایل تعیین شده تغییرات لازم را اعمال می‌کند تا کد هم خوانا و هم زیبا باشد.

اگر دنبال سفارشی‌سازی د

دقیق فرمت کدتان هستید (customization)، YAPF انتخاب خوبیه. خصوصا توی پروژه‌ها. البته اگر کسی باشه بشینه استاندارهای فرمت رو همه رو کانفیگ کنه.اما گاهی اوقات تنظیمات می‌تونه خیلی پیچیده بشه (complex configuration) و این ممکنه باعث سردرگمی شود.

خیلی ساده بخوام بگم YAPF بیشتر یک ابزار کانفیگ فرمته تا فرمتر با قواعد مشخص! یعنی میتونی یه جوری کانفیگ کنی که خروجی بشه مثه خروجی هر کدوم از دوتا قبلی، میتونی هم طوری کانفیگ کنی که اصلا هیچ شبیه دو تا قبلی نشه.



چند تا قطعه کد ببنید یه کم حس بگیرید به حرفام:

این کد رو در نظر بگیرید که فرمت خیلی بدی داره:

def compute(value1,value2,value3):return value1+value2+value3

Formatted by autopep8

def compute(value1, value2, value3): return value1 + value2 + value3

Formatted by Black

def compute(value1, value2, value3):

return value1 + value2 + value3

اما اینکه میگم به جز black اون دو تا دیگه متعین نیستن مثالش اینطوریه که فرض کنید کد ورودی این سه تا باشه. در این صورت با اینکه تابع یک چیزه ولی هر سه تا اینا قواعد YAPF رو رعایت کرد و هر سه تا میتونه تو پروژه باشه!


def function(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10):

print(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10)

def function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10):

print(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)

def function(

arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10):

print(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)


طبق تجربه میگم اگر گیت در پروژه تون نقش پررنگی داره قواعد فرمتیگ رو همون اول ست کنید وسط پروژه اعمال کردن فرمت شدیدا روی مرج کانفلیکت میده!

قواعد black به نظر من از جهت deterministic بودن خیلی خوبن ولی در زمینه‌ی طول خط خیلی کوتاه و سختگیرانه است.


تجربه شما چیه؟