رفتن به محتوای اصلی
برنامه‌سازی پیشرفته با پایتون درس‌نامهٔ آزاد
درس متوسط ۲۵ دقیقه

ماژول، پکیج و برنامه‌نویسی جنریک

واردات و فضاهای نام، ساختار پکیج، اعلان نوع، TypeVar و Protocol برای طراحی نوع‌محور.

هدف این درس

بتوانی پکیج مرتب بسازی و با typing و Protocol API انعطاف‌پذیر و امن طراحی کنی.

در این مطلب ۵

برنامهٔ بزرگ بدون مرزِ ماژول، یک فایل هزارخطیِ ترسناک می‌شود. ماژول‌بندی یعنی هر ایده یک خانه داشته باشد و قرارداد بین خانه‌ها روشن باشد.

واردات و فضاهای نام

# shop/cart.py
DISCOUNT = 0.1

def total(items):
    return sum(i["price"] * i["qty"] for i in items) * (1 - DISCOUNT)
# main.py — سه سبک واردات
import shop.cart                    # فضای نام کامل: shop.cart.total
from shop.cart import total         # مستقیم، ولی خطر تداخل نام
from shop import cart as cart_mod   # نام مستعار برای رفع تداخل

ساختار پکیج

shop/
├── __init__.py      # مرز پکیج؛ رابط عمومی را همین‌جا صادر کن
├── cart.py
├── pricing.py
└── tests/
    └── test_cart.py

__init__.py امروزه می‌تواند خالی باشد، اما بهترین جاست برای تعریف «رابط عمومی پکیج»: همان چیزهایی که کاربر پکیج باید ببیند، نه همهٔ جزئیات داخلی.

اعلان نوع: مستندِ قابل بررسی

def total(items: list[dict]) -> float:
    ...

اعلان نوع در زمان اجرا اجبار نمی‌شود؛ ارزشش خوانایی و بررسی ایستا با ابزارهایی مثل mypy است. جاهایی نوع بگذار که قرارداد را روشن می‌کند (مرز توابع و API عمومی)، نه هر متغیر داخلی.

جنریک: یک پیاده‌سازی برای همهٔ نوع‌ها

from typing import TypeVar, Generic

T = TypeVar("T")

class Stack(Generic[T]):
    def __init__(self) -> None:
        self._items: list[T] = []

    def push(self, item: T) -> None:
        self._items.append(item)

    def pop(self) -> T:
        return self._items.pop()

names: Stack[str] = Stack()

جاوا جنریک را با پاک‌سازی نوع (erasure) پیاده می‌کند؛ پایتون اصلاً در زمان اجرا نوع را پاک نمی‌کند چون از اول اجباری نبوده — جنریک پایتون کاملاً ابزار ایستا و مستندسازی است. دروغ نگو: Stack[str] جلوی push(123) را در زمان اجرا نمی‌گیرد.

Protocol: قرارداد بدون وراثت

from typing import Protocol

class Speaker(Protocol):
    def speak(self) -> str: ...

def morning_call(animal: Speaker) -> None:
    print(animal.speak())

هر شیئی که speak داشته باشد قبول است، بدون این‌که از کلاس مشترکی ارث برده باشد. این نزدیک‌ترین چیز به اینترفیس جاواست، ولی انعطاف‌پذیرتر: قرارداد ساختاری به‌جای سلسله‌مراتب اجباری.

سنجش فهم — ماژول و نوع

۰ از ۲ پاسخ داده شده

  1. Stack[str] در زمان اجرا جلوی push عدد را می‌گیرد؟
  2. تفاوت Protocol با ABC در یک جمله؟

اول به همهٔ پرسش‌ها پاسخ دهید، بعد بررسی کنید.

مطالب مرتبط

از همین بخش و با برچسب‌های مشترک

این مطلب را خواندید؟ آن را علامت بزنید تا پیشرفت شما روی همین دستگاه ذخیره شود.

وضعیت پیشرفت برای ماژول، پکیج و برنامه‌نویسی جنریک