Kahibaro
Discord Login Register

متد `__init__`

نقش متد `__init__` در کلاس‌ها

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

متد سازنده (Constructor) چیست؟

وقتی از روی یک کلاس، شیء جدید می‌سازید (مثلاً User() یا Car())، پایتون می‌تواند به‌طور خودکار کدی را اجرا کند تا آن شیء را «آمادهٔ استفاده» کند.
این کار با متدی به نام __init__ انجام می‌شود.

به‌صورت ساده:

ساختار کلی:

python
class ClassName:
    def __init__(self, پارامترها):
        # کد مقداردهی اولیه
        ...

شکل کلی `__init__` و نقش `self`

رایج‌ترین امضا (signature) برای __init__ به این شکل است:

python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

نکته‌ها:

مثال استفاده:

python
p1 = Person("Ali", 20)
print(p1.name)  # خروجی: Ali
print(p1.age)   # خروجی: 20

هنگام اجرای Person("Ali", 20) در پشت صحنه این اتفاق می‌افتد:

۱. پایتون یک شیء خالی از کلاس Person می‌سازد.
۲. سپس به‌طور خودکار صدا می‌زند:

python
Person.__init__(p1, "Ali", 20)

(که در کد ما به صورت def __init__(self, name, age): تعریف شده است.)

مقداردهی ویژگی‌ها با `__init__`

مهم‌ترین کاربرد __init__، مقداردهی ویژگی‌های شیء است:

python
class Book:
    def __init__(self, title, pages, price):
        self.title = title
        self.pages = pages
        self.price = price
b = Book("Python for Beginners", 250, 150000)
print(b.title)  # Python for Beginners

الگوی ذهنی خوب:

$$
\text{پارامتر تابع} \longrightarrow \text{self.ویژگی}
$$

`__init__` بدون پارامتر (به‌جز `self`)

لازم نیست همیشه __init__ پارامترهای اضافی داشته باشد.
گاهی فقط می‌خواهیم مقادیر پیش‌فرض بگذاریم:

python
class Counter:
    def __init__(self):
        self.value = 0
c = Counter()
print(c.value)  # 0

اینجا سازنده هیچ ورودی از بیرون نمی‌گیرد، اما درون خودش مقداردهی اولیه انجام می‌دهد.

مقادیر پیش‌فرض پارامترها در `__init__`

مثل توابع عادی، در __init__ هم می‌توانید پارامترهای اختیاری با مقدار پیش‌فرض داشته باشید:

python
class User:
    def __init__(self, username, is_admin=False):
        self.username = username
        self.is_admin = is_admin
u1 = User("ali")                 # is_admin = False
u2 = User("admin_user", True)    # is_admin = True

اینجا:

این کار ساخت اشیاء را انعطاف‌پذیرتر می‌کند.

تفاوت `__init__` با متدهای عادی

همهٔ متدهای کلاس از نظر شکل کلی شبیه‌اند، اما __init__ چند تفاوت مهم دارد:

مثال مقایسه:

python
class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self.balance = balance  # مقدار اولیه
    def deposit(self, amount):
        self.balance += amount  # عمل روی داده‌های موجود
acc = BankAccount("Sara", 1000)  # __init__ خودکار اجرا می‌شود
acc.deposit(500)                 # متد عادی، دستی فراخوانی می‌شود
print(acc.balance)               # 1500

اعتبارسنجی ورودی‌ها در `__init__`

می‌توانید در __init__ ورودی‌ها را بررسی کنید و در صورت نامعتبر بودن، خطا بدهید یا اصلاح کنید:

python
class Product:
    def __init__(self, name, price):
        self.name = name
        if price < 0:
            raise ValueError("قیمت نمی‌تواند منفی باشد")
        self.price = price
# p = Product("Phone", -100)  # این خط خطا ایجاد می‌کند

این کار کمک می‌کند هر شیء ساخته‌شده، حالت معتبری داشته باشد.

استفاده از `__init__` برای محاسبات اولیه

گاهی لازم است قبل از استفاده از شیء، یک‌سری محاسبات اولیه انجام شود.
این کار نیز جای خوبی در __init__ دارد:

python
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.area = width * height  # محاسبه و ذخیرهٔ مساحت
r = Rectangle(3, 4)
print(r.area)  # 12

پارامترهای زیاد در `__init__` (و توصیهٔ عملی)

مثلاً:

python
class Student:
    def __init__(self, first_name, last_name, age, student_id, major, gpa):
        self.first_name = first_name
        self.last_name = last_name
        self.age = age
        self.student_id = student_id
        self.major = major
        self.gpa = gpa

نکتهٔ عملی:

python
s = Student(first_name="Ali", last_name="Ahmadi",
            age=21, student_id="401234",
            major="CS", gpa=18.5)

چند نمونهٔ ساده از کلاس‌ها با `__init__`

مثال: کلاس کاربر ساده

python
class SimpleUser:
    def __init__(self, username, email):
        self.username = username
        self.email = email
    def info(self):
        return f"{self.username} - {self.email}"
u = SimpleUser("ali", "ali@example.com")
print(u.info())  # ali - ali@example.com

اینجا __init__ فقط اطلاعات اولیه را ذخیره می‌کند، متد info از آن‌ها استفاده می‌کند.

مثال: شمارنده با مقدار شروع دلخواه

python
class Counter:
    def __init__(self, start=0):
        self.value = start
    def increment(self):
        self.value += 1
c1 = Counter()       # شروع از 0
c2 = Counter(10)     # شروع از 10
c1.increment()
c2.increment()
print(c1.value)  # 1
print(c2.value)  # 11

آیا می‌توان کلاس بدون `__init__` داشت؟

بله. اگر __init__ تعریف نکنید، پایتون خودش یک سازندهٔ پیش‌فرض در نظر می‌گیرد که هیچ کار خاصی انجام نمی‌دهد:

python
class Empty:
    pass
e = Empty()  # بدون __init__ هم کار می‌کند

اما:

نکات رایج و اشتباهات معمول با `__init__`

۱. فراموش کردن self:

python
class Person:
    def __init__(name, age):   # اشتباه: self باید اولین پارامتر باشد
        name = name
        age = age

درست:

python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

۲. استفاده نکردن از self.:

python
class Person:
    def __init__(self, name):
        name = name  # این فقط یک متغیر محلی است، روی شیء ذخیره نمی‌شود

درست:

python
class Person:
    def __init__(self, name):
        self.name = name  # حالا روی شیء ذخیره می‌شود

۳. ندادن آرگومان کافی هنگام ساخت شیء:

python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
p = Person("Ali")  # TypeError: آرگومان age داده نشده

باید:

python
p = Person("Ali", 20)

یا سن را پیش‌فرض کنید:

python
class Person:
    def __init__(self, name, age=18):
        self.name = name
        self.age = age

تمرین‌های پیشنهادی

برای تمرین، این ایده‌ها را پیاده‌سازی کنید:

  1. کلاسی به نام Dog تعریف کنید که در __init__ نام و نژاد سگ را بگیرد و یک متد bark داشته باشد که پیامی شامل نام سگ چاپ کند.
  2. کلاسی به نام Point بسازید که مختصات $x$ و $y$ را در __init__ بگیرد و در همان‌جا فاصله از مبدأ را در ویژگی‌ای به نام distance_from_origin حساب و ذخیره کند.
  3. کلاسی به نام Movie تعریف کنید که عنوان، سال تولید و امتیاز را در __init__ بگیرد و اگر امتیاز کمتر از ۰ یا بیشتر از ۱۰ بود، آن را به نزدیک‌ترین مقدار معتبر (۰ یا ۱۰) محدود کند.

در این تمرین‌ها فقط روی استفاده از __init__ برای مقداردهی اولیه، اعتبارسنجی و محاسبهٔ اولیه تمرکز کنید.

Views: 6

Comments

Please login to add a comment.

Don't have an account? Register now!