برنامهٔ بزرگ بدون مرزِ ماژول، یک فایل هزارخطیِ ترسناک میشود. ماژولبندی یعنی هر ایده یک خانه داشته باشد و قرارداد بین خانهها روشن باشد.
واردات و فضاهای نام
# 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 داشته باشد قبول است، بدون اینکه از کلاس مشترکی ارث برده باشد. این نزدیکترین چیز به اینترفیس جاواست، ولی انعطافپذیرتر: قرارداد ساختاری بهجای سلسلهمراتب اجباری.
سنجش فهم — ماژول و نوع
۰ از ۲ پاسخ داده شده