فصل سوم: الفبای تایپ‌هینت

Please login to bookmark Close

چالش

تابعی داریم که سبد خرید را حساب می‌کند:

def calculate_total(items, discount, apply_tax):
    ...

از امضای این تابع معلوم نیست items لیست است یا دیکشنری یا لیستی از دیکشنری‌ها، discount عدد است یا درصدی به صورت رشته، و apply_tax بولین است یا نرخ مالیات. برای رسیدن به پاسخ باید بدنه‌ی تابع را بخوانید یا جایی را که تابع صدا زده می‌شود پیدا کنید. این فصل نشان می‌دهد که چگونه چنین ابهامی از ابتدا شکل نگیرد.

تایپ‌های پایه

پایتون چهار نوعِ ساده دارد که بیشترِ کدها از آن‌ها ساخته می‌شوند:

name: str = "Ali"
age: int = 32
price: float = 99.5
is_active: bool = True

روی توابع هم همین شکل کار می‌کند:

def create_user(name: str, age: int, is_active: bool) -> str:
    return f"{name} ({age})"

وقتی تابع چیزی برنمی‌گرداند

اگر تابعی مقداری برنمی‌گرداند، خروجی‌اش None است:

def log_error(message: str) -> None:
    print(f"ERROR: {message}")

-> None را حتماً بنویسید، زیرا در نبودِ آن mypy در حالت سخت‌گیرانه نوعِ خروجی را نامعلوم فرض می‌کند و خطا نمایش می‌دهد.

مقدار پیش‌فرض

در صورتی که بخواهید برای ورودی های تابع، مقدار پیش‌فرض در نظر بگیرید، هینت و مقدار پیش‌فرض کنار هم می‌آیند:

def create_user(name: str, age: int = 18, is_active: bool = True) -> str:
    ...

ترتیب اهمیت دارد: اول نوع، بعد مساوی، بعد مقدار.

لیست

names: list[str] = ["Ali", "Sara"]
scores: list[int] = [90, 85, 77]

list[str] یعنی لیستی که همه‌ی عناصرش رشته‌اند.

def get_names(users: list[dict]) -> list[str]:
    return [u["name"] for u in users]

دیکشنری

dict دو نوع تایپ‌هینت می‌گیرد: کلید و مقدار.

prices: dict[str, float] = {"laptop": 1200.0, "mouse": 25.5}

اولی نوعِ کلید است و دومی نوعِ مقدار.

تاپل

تاپل دو حالت دارد و اشتباه گرفتنِ این دو حالت رایج است.

تاپلِ ثابت — تعداد و نوعِ هر عنصر مشخص است:

point: tuple[int, int] = (10, 20)
user_row: tuple[int, str, bool] = (1, "Ali", True)

تاپلِ کشسان — همه‌ی عناصر یک نوع دارند و تعدادشان معلوم نیست:

scores: tuple[int, ...] = (90, 85, 77, 60)

توجه کنید که آن سه نقطه بخشی از سینتکس است، نه جای خالی، و معنایش «و همین‌طور تا آخر» است.

مجموعه

tags: set[str] = {"python", "typing"}

تودرتو

این نوع‌ها را به هر اندازه که لازم باشد می‌توان تو در تو نوشت:

orders: dict[str, list[int]] = {
    "user_1": [101, 102],
    "user_2": [103],
}

این یعنی دیکشنری‌ای که کلیدش رشته و مقدارش لیستی از عددهای صحیح است.

در برخورد با تایپی مثل نمونه‌ی زیر:

def process(data: dict[str, list[tuple[int, str]]]) -> None:
    ...

به یاد داشته باشید که راهِ خواناتری وجود دارد؛ در فصل ششم با TypeAlias آشنا می‌شوید.

سبک قدیمی

در کدهای قبل از پایتون ۳.۹ این شکل دیده می‌شود:

from typing import List, Dict, Tuple, Set

names: List[str] = ["Ali"]
prices: Dict[str, float] = {}

این شکل هنوز کار می‌کند، اما دیگر توصیه نمی‌شود، زیرا از پایتون ۳.۹ به بعد خودِ list و dict و tuple نوع می‌پذیرند و به import نیازی نیست. قاعده‌ی ساده این است: کدِ جدید را با حرفِ کوچک بنویسید و کدِ قدیمی را هر وقت به آن دست زدید به‌مرور اصلاح کنید.

باور غلط رایج

بسیاری فکر می‌کنند list[str] جلوی اضافه کردنِ عدد به لیست را می‌گیرد، در حالی که چنین نیست:

names: list[str] = ["Ali"]
names.append(42)   # پایتون هیچ اعتراضی نمی‌کند

تنها mypy و Pylance به این کد اعتراض می‌کنند.

خلاصه

در این فصل گرامر پایه‌ی تایپ‌هینت را آموختید: نوع پارامترها، نوع خروجی و نوع محتوای کالکشن‌ها. با همین چند الگو می‌توانید امضای بیشتر توابع پروژه را گویا کنید.

  • امضای تابع: نوع ورودی را با x: int و نوع خروجی را با -> int اعلام کنید.
  • تابع بدون خروجی: -> None را حتماً بنویسید، وگرنه mypy در حالت سخت‌گیرانه بررسی را ادامه نمی‌دهد.
  • کالکشن‌ها: نوع محتوا داخل براکت می‌آید و می‌تواند تودرتو باشد، مانند dict[str, list[int]].
  • دو چهره‌ی تاپل: حالت ثابت tuple[int, str] تعداد معینی دارد و حالت کشسان tuple[int, ...] تعداد نامعلوم.
  • سبک تازه: از پایتون ۳.۹ به بعد List و Dict را کنار بگذارید و از نام کوچک استفاده کنید.
سینتکسمعنانمونه
str ، int ، float ، boolنوع‌های پایهage: int = 32
-> Noneتابع مقداری برنمی‌گرداندdef log(m: str) -> None
list[str]لیستی از رشته‌هاnames: list[str]
dict[str, float]دیکشنری با کلید و مقدار معینprices: dict[str, float]
tuple[int, ...]تاپل کشسان از یک نوعscores: tuple[int, ...]
set[str]مجموعه‌ی رشته‌هاtags: set[str]

در فصل بعد

تا اینجا هر متغیر دقیقاً یک نوع داشت، در حالی که در بسیاری از کدها یک مقدار می‌تواند غایب باشد یا از چند نوع مختلف باشد. فصل بعد به همین دو حالت می‌پردازد.

Please login to bookmark Close
نظرات

دیدگاهتان را بنویسید

پیشرفت
فهرست مطالب

سرفصل دوره

تمرین

این قسمت تمرین ندارد!

پاسخ تمرین ها

هنوز برای تمرین‌های این قسمت پاسخی ثبت نشده است!

اشتراک گذاری

چرا بهتره از فیلترشکن استفاده کنید؟

من همه ویدئو ها و پادکست های کُدباز رو توی یوتیوب و ساندکلود و پلتفرم هایی آپلود می‌کنم که اغلب فیلتر هستند.

اغلب آموزش‌ها ویدئو و پادکست دارند. پس اگر می‌خواهید از محتوای سایت بیشترین استفاده رو ببرید نیاز به فیلتر شکن دارید.

توجه داشته باشید که برای خرید از فروشگاه بهتره فیلتر شکن رو خاموش کنید.

تنظیمات

انتخاب زبان
تغییر تم