کدی که خودش را توضیح میدهد
دو ابزار کد را برای انسانها و ابزارها خواناتر میکنند: docstring که میگوید تابع چه میکند، و type hint که میگوید چه نوعی میگیرد و برمیگرداند.
docstring
اولین رشتهی داخل بدنهی تابع، کلاس یا ماژول، docstring آن است. طبق قرارداد با سه دابلکوتیشن نوشته میشود:
def rug_price(width_cm: int, length_cm: int, price_per_sqm: int) -> int:
"""قیمت فرش را بر اساس ابعاد و قیمت هر متر مربع حساب میکند.
width_cm و length_cm بر حسب سانتیمتر و قیمت بر حسب ریال است.
نتیجه به نزدیکترین ریال گرد میشود.
"""
area = width_cm * length_cm / 10_000
return round(area * price_per_sqm)
help(rug_price) # docstring را نشان میدهد
print(rug_price.__doc__)
خط اول یک جملهی خلاصه است؛ سپس یک خط خالی و جزئیات. VS Code با نگه داشتن ماوس روی نام تابع همین متن را نمایش میدهد. docstring بگوید «چه» و «چرا»؛ «چطور» را خود کد نشان میدهد.
type hints
از پایتون ۳.۵ میتوانید نوع پارامترها و خروجی را اعلام کنید. نکتهی بسیار مهم: پایتون در زمان اجرا این نوعها را بررسی نمیکند. rug_price("200", 300, 1) با وجود hint اجرا میشود (و البته جای دیگری خطا میدهد). ارزش hint ها در ابزارهاست: Pylance در VS Code، mypy و Ruff اشتباه را قبل از اجرا زیر کد خط قرمز میکشند و تکمیل خودکار دقیقتر میشود.
| hint | معنی |
|---|---|
int، str، float، bool | انواع ساده |
list[str] | لیستی از رشتهها (از 3.9 بدون import) |
dict[str, int] | دیکشنری با کلید رشته و مقدار عدد |
tuple[int, int] | تاپل دقیقاً دوتایی |
int | None | عدد یا None (از 3.10) |
-> None | تابع چیزی برنمیگرداند |
def find_order(orders: list[dict], code: str) -> dict | None:
for order in orders:
if order["code"] == code:
return order
return None
def city_totals(rows: list[tuple[str, int]]) -> dict[str, int]:
totals: dict[str, int] = {}
for city, amount in rows:
totals[city] = totals.get(city, 0) + amount
return totals
با dict | None در خروجی، Pylance اگر بدون بررسی None بنویسید find_order(...)["price"] هشدار میدهد؛ یعنی یک باگ واقعی قبل از اجرا گرفته شده است.
در این دورهی مقدماتی hint را در حد همین جدول نگه میداریم. مباحثی مثل Protocol، TypeVar و generic ها در دورهی پایتون پیشرفته آمدهاند.
نکتههایی که کمتر کسی میداند
- در VS Code تنظیم
python.analysis.typeCheckingModeرا رویbasicیاstandardبگذارید تا Pylance خطاهای نوع را واقعاً گزارش کند؛ پیشفرض آن off است. - اگر اولین عبارت تابع یک f-string باشد، docstring حساب نمیشود و
__doc__برابر None است؛ docstring باید رشتهی ثابت باشد. list[int]در زمان اجرا چیزی را محدود نمیکند؛isinstance(x, list[int])حتی خطا میدهد. hint برای ابزارهاست، نه اعتبارسنجی.- برای مستندسازی واحد، hint جای خوبی نیست؛ واحد را در نام پارامتر بیاورید (
width_cm) که هم در کد و هم در فراخوانی دیده میشود. - متغیر را هم میتوان annotate کرد (
totals: dict[str, int] = {})؛ برای ظرفهای خالی که ابزار نمیتواند نوعشان را حدس بزند بسیار مفید است.