فصل ۵: توابع — از تعریف ساده تا scope و بازگشت

docstring و type hints مقدماتی

کدی که خودش را توضیح می‌دهد

دو ابزار کد را برای انسان‌ها و ابزارها خواناتر می‌کنند: 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] = {})؛ برای ظرف‌های خالی که ابزار نمی‌تواند نوعشان را حدس بزند بسیار مفید است.

برای ذخیره‌ی پیشرفت و شرکت در آزمون، وارد شوید — رایگان است.