۸

ماژول‌ها و پکیج‌ها 📦

یاد می‌گیریم چطور کدهامون رو سازماندهی کنیم!

ماژول‌های استاندارد پایتون

پایتون کتابخانه استاندارد غنی داره که شامل ماژول‌های زیادی میشه:

استفاده از ماژول‌های استاندارد
# import کامل ماژول
import math
import random
import datetime

# استفاده از ماژول math
print("جذر 16:", math.sqrt(16))  # 4.0
print("عدد پی:", math.pi)        # 3.141592653589793

# استفاده از ماژول random
print("عدد تصادفی بین 1 تا 10:", random.randint(1, 10))
print("انتخاب تصادفی:", random.choice(["سیب", "موز", "پرتقال"]))

# استفاده از ماژول datetime
now = datetime.datetime.now()
print("تاریخ و زمان فعلی:", now)
print("سال فعلی:", now.year)

# import با نام مستعار
import math as m
print("جذر 25:", m.sqrt(25))  # 5.0

# import فقط بخشی از ماژول
from math import sqrt, pi
print("جذر 9:", sqrt(9))  # 3.0
print("عدد پی:", pi)       # 3.141592653589793

# import همه چیز از ماژول (توصیه نمی‌شود)
from math import *
print("سینوس 0:", sin(0))  # 0.0

ایجاد ماژول‌های شخصی

می‌تونیم ماژول‌های خودمون رو ایجاد کنیم و ازشون استفاده کنیم:

فایل: utils.py
# این یک ماژول شخصی است

def add(a, b):
    """دو عدد را با هم جمع می‌کند"""
    return a + b

def subtract(a, b):
    """دو عدد را از هم کم می‌کند"""
    return a - b

def multiply(a, b):
    """دو عدد را در هم ضرب می‌کند"""
    return a * b

def divide(a, b):
    """عدد اول را بر عدد دوم تقسیم می‌کند"""
    if b == 0:
        return "خطا: تقسیم بر صفر"
    return a / b

# متغیرهای ماژول
PI = 3.14159
VERSION = "1.0"

# کد تست برای زمانی که ماژول مستقیماً اجرا شود
if __name__ == "__main__":
    print("تست ماژول utils:")
    print("جمع 5 و 3:", add(5, 3))
    print("ضرب 4 و 5:", multiply(4, 5))
فایل: main.py
# استفاده از ماژول شخصی
import utils

result = utils.add(10, 5)
print("نتیجه جمع:", result)  # 15

print("عدد پی از ماژول:", utils.PI)  # 3.14159

# یا با import انتخابی
from utils import multiply, VERSION

result = multiply(4, 5)
print("نتیجه ضرب:", result)  # 20
print("ورژن ماژول:", VERSION)  # 1.0

# import با نام مستعار
import utils as u
print("تفریق 10 و 4:", u.subtract(10, 4))  # 6

پکیج‌ها (Packages)

پکیج‌ها مجموعه‌ای از ماژول‌های مرتبط هستند که در یک دایرکتوری قرار دارن:

ساختار پکیج
my_package/
    __init__.py
    math_utils.py
    string_utils.py
    validators.py
    sub_package/
        __init__.py
        advanced.py
استفاده از پکیج
# import از پکیج
import my_package.math_utils
from my_package import string_utils
from my_package.validators import is_email_valid

# فایل __init__.py می‌تواند imports را ساده‌تر کند
# محتوای __init__.py:
# from .math_utils import add, subtract
# from .string_utils import capitalize, reverse
# from .validators import is_email_valid, is_phone_valid

# سپس می‌توان اینطور استفاده کرد:
# from my_package import add, capitalize, is_email_valid

# import از ساب پکیج
from my_package.sub_package.advanced import complex_calculation
مثال فایل‌های پکیج
# فایل: my_package/math_utils.py
def add(a, b):
    return a + b

def subtract(a, b):
    return a - b

def multiply(a, b):
    return a * b

# فایل: my_package/string_utils.py
def capitalize(text):
    return text.capitalize()

def reverse(text):
    return text[::-1]

# فایل: my_package/__init__.py
from .math_utils import add, subtract, multiply
from .string_utils import capitalize, reverse
from .validators import is_email_valid

ماژول‌های مفید استاندارد

برخی از ماژول‌های بسیار مفید کتابخانه استاندارد:

ماژول‌های کاربردی
# ماژول os برای کار با سیستم عامل
import os
print("مسیر دایرکتوری فعلی:", os.getcwd())
print("لیست فایل‌های دایرکتوری:", os.listdir())

# ایجاد دایرکتوری جدید
os.makedirs("new_folder", exist_ok=True)

# ماژول sys برای کار با سیستم
import sys
print("نسخه پایتون:", sys.version)
print("آرگومان‌های خط فرمان:", sys.argv)

# ماژول json برای کار با JSON
import json
data = {'name': 'علی', 'age': 25, 'city': 'تهران'}
json_str = json.dumps(data, ensure_ascii=False)  # تبدیل به رشته JSON
print("JSON رشته:", json_str)

# تبدیل برگشت از JSON
parsed_data = json.loads(json_str)
print("داده parsed:", parsed_data)

# ماژول re برای عبارات با قاعده
import re
pattern = r'\d+'  # یک یا چند رقم
text = "عمر من 25 سال و وزنم 70 کیلوگرم است"
numbers = re.findall(pattern, text)
print("اعداد پیدا شده:", numbers)  # ['25', '70']

# ماژول collections برای ساختارهای داده پیشرفته
from collections import Counter, defaultdict

words = ["apple", "banana", "apple", "orange", "banana", "apple"]
word_count = Counter(words)
print("تعداد کلمات:", word_count)

# ماژول itertools برای iterator tools
from itertools import permutations, combinations

print("جایگشت های ABC:", list(permutations("ABC")))
print("ترکیب های ABC:", list(combinations("ABC", 2)))

نکات مهم و بهترین practices

برخی نکات مهم در کار با ماژول‌ها و پکیج‌ها:

نکات مهم
# 1. از import * خودداری کنید (مگر در __init__.py)
# بد: from math import *
# خوب: from math import sqrt, pi

# 2. از نام‌های مستعار مناسب استفاده کنید
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 3. ترتیب imports را رعایت کنید:
# 1. imports استاندارد
# 2. imports third-party
# 3. imports داخلی/محلی

# 4. از if __name__ == "__main__" استفاده کنید
def main():
    print("این زمانی اجرا می‌شود که فایل مستقیماً run شود")

if __name__ == "__main__":
    main()

# 5. از relative imports در پکیج‌ها استفاده کنید
# from . import module
# from .module import function
# from ..parent_package import module

# 6. مستندسازی ماژول‌ها
"""ماژول utilities
این ماژول شامل توابع کمکی برای پروژه است
"""

# 7. مدیریت خطا در imports
try:
    import requests
except ImportError:
    print("لطفا requests را نصب کنید: pip install requests")
    exit(1)

تمرین! 🧠

یک پکیج به نام `shopping` ایجاد کنید که شامل ماژول‌های زیر باشد:

  1. `cart.py` - برای مدیریت سبد خرید
  2. `products.py` - برای مدیریت محصولات
  3. `discounts.py` - برای مدیریت تخفیف‌ها

سپس یک فایل main.py بنویسید که از این پکیج استفاده کند و یک سیستم ساده خرید ایجاد کند.

جواب تمرین

# فایل: shopping/__init__.py
from .products import Product, get_products
from .cart import ShoppingCart
from .discounts import apply_discount

# فایل: shopping/products.py
class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price

def get_products():
    return [
        Product("لپ‌تاپ", 10000000),
        Product("ماوس", 500000),
        Product("کیبورد", 800000)
    ]

# فایل: shopping/cart.py
class ShoppingCart:
    def __init__(self):
        self.items = []
    
    def add_item(self, product, quantity=1):
        self.items.append({"product": product, "quantity": quantity})
    
    def total(self):
        return sum(item["product"].price * item["quantity"] for item in self.items)
    
    def display(self):
        for item in self.items:
            print(f"{item['product'].name} - {item['quantity']} عدد - {item['product'].price} تومان")

# فایل: shopping/discounts.py
def apply_discount(total, discount_percent):
    return total * (1 - discount_percent / 100)

# فایل: main.py
from shopping import get_products, ShoppingCart, apply_discount

def main():
    products = get_products()
    cart = ShoppingCart()
    
    print("محصولات موجود:")
    for i, product in enumerate(products, 1):
        print(f"{i}. {product.name} - {product.price} تومان")
    
    while True:
        choice = input("عدد محصول را انتخاب کنید (0 برای پایان): ")
        if choice == "0":
            break
        try:
            product = products[int(choice) - 1]
            quantity = int(input("تعداد: "))
            cart.add_item(product, quantity)
            print("به سبد خرید اضافه شد!")
        except (IndexError, ValueError):
            print("انتخاب نامعتبر!")
    
    print("\nسبد خرید شما:")
    cart.display()
    
    total = cart.total()
    print(f"\nجمع کل: {total} تومان")
    
    if input("آیا کد تخفیف دارید؟ (y/n) ").lower() == "y":
        discount = float(input("درصد تخفیف: "))
        total = apply_discount(total, discount)
        print(f"قیمت نهایی بعد از تخفیف: {total} تومان")

if __name__ == "__main__":
    main()