Table of Contents
تفاوت «ویژگی» و «متد» در کلاسها
در فصل اصلی OOP با مفهوم کلی کلاس و شیء آشنا شدهاید. در این بخش روی دو جزء مهم هر کلاس تمرکز میکنیم:
- ویژگیها (Attributes / Properties): دادهها و اطلاعاتی که یک شیء نگه میدارد.
- متدها (Methods): توابعی که روی آن دادهها عمل میکنند یا رفتاری برای شیء تعریف میکنند.
به صورت شهودی:
- ویژگی = «چیزهایی که یک شیء دارد»
- متد = «کارهایی که یک شیء انجام میدهد»
مثال: یک شیء از کلاس Car ممکن است:
- ویژگی داشته باشد:
color،speed - متد داشته باشد:
start()،stop()،accelerate()
تعریف ویژگیها در کلاس
ویژگیهای شیء (ویژگیهای نمونه، Instance Attributes)
متداولترین نوع ویژگیها، ویژگیهای مربوط به هر شیء هستند؛ یعنی هر نمونه از کلاس مقدار خودش را دارد.
برای ایجاد این ویژگیها معمولاً از متد __init__ استفاده میکنیم (جزئیات خود __init__ در فصل جداگانه آمده است؛ اینجا فقط استفادهاش را برای ویژگیها نشان میدهیم):
class Person:
def __init__(self, name, age):
self.name = name # ویژگی شیء
self.age = age # ویژگی شیء
p1 = Person("Ali", 20)
p2 = Person("Sara", 25)
print(p1.name, p1.age) # Ali 20
print(p2.name, p2.age) # Sara 25نکات مهم:
self.nameوself.ageویژگیهای شیء هستند.- هر شیء (
p1وp2) نسخهی خودش از این ویژگیها را دارد. - تغییر یک ویژگی روی یک شیء، دیگری را تغییر نمیدهد:
p1.age = 21
print(p1.age) # 21
print(p2.age) # 25ویژگیهای کلاس (Class Attributes) – مقدمه کوتاه
برخی ویژگیها برای همهی اشیاء یکسان هستند؛ اینها را معمولاً به صورت مستقیم در بدنهی کلاس تعریف میکنیم:
class Person:
species = "Human" # ویژگی کلاس - بین همهی اشیاء مشترک است
def __init__(self, name):
self.name = name
p1 = Person("Ali")
p2 = Person("Sara")
print(p1.species) # Human
print(p2.species) # Humanدر این فصل تمرکز اصلی روی تفاوت «ویژگی» و «متد» است؛ تفاوت ویژگی کلاس و ویژگی شیء را در فصلهای بعدی میتوان بیشتر گسترش داد. همینقدر بدانید:
- ویژگیای که خارج از متدها و داخل کلاس تعریف شود → معمولا ویژگی کلاس است.
- ویژگیای که به صورت
self.چیزیدر متد (معمولاً__init__) تعریف شود → ویژگی شیء است.
تعریف متدها در کلاس
متدها در واقع توابعی هستند که داخل کلاس تعریف میشوند و معمولاً روی ویژگیهای همان شیء کار میکنند.
ساختار کلی:
class ClassName:
def method_name(self, other_parameters):
# کاری انجام بده
...
نکتهی مهم: اولین پارامتر متدهای نمونه تقریباً همیشه self است.
یک مثال ساده از متد
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say_hello(self):
print(f"سلام! من {self.name} هستم و {self.age} سالمه.")
p = Person("Ali", 20)
p.say_hello()
# خروجی: سلام! من Ali هستم و 20 سالمه.اینجا:
say_helloیک متد است.self.nameوself.ageویژگیهای شیء هستند.- متد با استفاده از
selfبه ویژگیها دسترسی دارد.
چرا باید از `self` استفاده کنیم؟
selfنمایندهی همان شیئی است که متد روی آن صدا زده میشود.- وقتی مینویسید
p.say_hello()، پایتون در پشت صحنه آن را به شکلPerson.say_hello(p)صدا میزند. - بنابراین
selfدرون متد، در این مثال همانpاست.
پس:
- ویژگیها را همیشه با
self.(برای شیء فعلی) مینویسیم:self.age - متدها هم اولین پارامترشان
selfاست تا بدانند روی کدام شیء کار کنند.
کار با ویژگیها در متدها
متدها معمولاً سه کار اصلی با ویژگیها انجام میدهند:
- خواندن مقدار ویژگیها
- تغییر دادن مقدار ویژگیها
- استفادهی ترکیبی از چند ویژگی برای یک محاسبه
مثال: تغییر ویژگی در متد
class BankAccount:
def __init__(self, owner, balance):
self.owner = owner
self.balance = balance # موجودی
def deposit(self, amount):
self.balance += amount # افزایش موجودی
def withdraw(self, amount):
self.balance -= amount # کاهش موجودی
def show_balance(self):
print(f"موجودی حساب {self.owner}: {self.balance} تومان")
acc = BankAccount("Ali", 1000)
acc.deposit(500) # واریز
acc.withdraw(200) # برداشت
acc.show_balance() # موجودی حساب Ali: 1300 توماندر این مثال:
ownerوbalanceویژگیاند.deposit،withdrawوshow_balanceمتد هستند.- متدها روی ویژگیها کار میکنند تا «رفتار» حساب بانکی را بسازند.
متدهایی با پارامتر
همانطور که توابع معمولی پارامتر میگیرند، متدها هم علاوه بر self میتوانند پارامتر داشته باشند.
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def resize(self, new_width, new_height):
self.width = new_width
self.height = new_height
def area(self):
return self.width * self.height
rect = Rectangle(2, 3)
print(rect.area()) # 6
rect.resize(5, 4)
print(rect.area()) # 20resizeپارامترهایnew_widthوnew_heightرا میگیرد و ویژگیها را بهروز میکند.areaاز ویژگیها استفاده میکند و یک مقدار برمیگرداند (رفتار محاسباتی).
متدها در مقابل توابع عادی
تابع عادی:
- بیرون از کلاس تعریف میشود.
- معمولاً روی دادههایی کار میکند که به صورت پارامتر به آن داده میشود.
متد:
- داخل کلاس تعریف میشود.
- روی دادههایی کار میکند که به عنوان ویژگیهای شیء ذخیره شدهاند.
- همیشه حداقل یک پارامتر
selfدارد (برای متدهای نمونه).
مقایسه:
# تابع عادی
def full_name(first, last):
return first + " " + last
# کلاس با متد
class Person:
def __init__(self, first, last):
self.first = first
self.last = last
def full_name(self):
return self.first + " " + self.lastدر تابع عادی:
- باید هر بار
firstوlastرا بدهید.
در متد:
- یک بار در ساختن شیء ویژگیها تنظیم میشود؛
- بعد میتوان بارها از متد استفاده کرد و متد خودش میداند روی چه دادهای کار کند (
self.first,self.last).
تغییر و اضافهکردن ویژگی به صورت پویا
در پایتون میتوانید بعد از ساخته شدن شیء، به آن ویژگی جدید اضافه کنید یا ویژگی موجود را عوض کنید.
تغییر ویژگی موجود
class Person:
def __init__(self, name):
self.name = name
p = Person("Ali")
print(p.name) # Ali
p.name = "Reza"
print(p.name) # Rezaاضافهکردن ویژگی جدید بیرون از کلاس
class Person:
def __init__(self, name):
self.name = name
p = Person("Ali")
p.age = 20 # تعریف یک ویژگی جدید به صورت پویا
print(p.name, p.age) # Ali 20
این انعطافپذیری بالاست، ولی برای کدهای بزرگتر بهتر است ویژگیهای اصلی را در __init__ تعریف کنید تا ساختار شیء قابل پیشبینی باشد.
متدهای نمونه در مقابل متدهای کلاس و استاتیک (نگاه مقدماتی)
به طور کلی سه نوع متد وجود دارد (در این فصل فقط نوع اول را جدی استفاده میکنیم):
- متد نمونه (Instance Method)
- رایجترین نوع؛ متدی که اولین پارامترش
selfاست. - روی یک شیء خاص کار میکند و به ویژگیهای آن دسترسی دارد.
- متد کلاس (Class Method)
- معمولاً با دکوراتور
@classmethodمشخص میشود و اولین پارامترشclsاست. - روی خود کلاس کار میکند، نه روی یک شیء خاص.
- متد استاتیک (Static Method)
- با
@staticmethodمشخص میشود. - مثل یک تابع عادی است که فقط برای نظمدهی داخل کلاس قرار گرفته.
در این فصل هدفتان این است که:
- متدهای نمونه (همانهایی که
selfدارند) را خوب درک و استفاده کنید. - بدانید که دو نوع دیگر هم وجود دارد، ولی جزئیاتشان میتواند در سطح پیشرفتهتر پوشش داده شود.
چند الگوی متداول برای متدها
متد «نمایشی» (`show`، `info` و …)
متدی که اطلاعات شیء را چاپ میکند:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(f"نام: {self.name}, سن: {self.age}")
p = Person("Sara", 30)
p.info()متد «تغییر حالت» (state-changing)
متدی که وضعیت شیء را عوض میکند:
class Light:
def __init__(self):
self.is_on = False
def turn_on(self):
self.is_on = True
def turn_off(self):
self.is_on = False
lamp = Light()
lamp.turn_on()
print(lamp.is_on) # Trueمتد «محاسباتی» با مقدار بازگشتی
متدی که بر اساس ویژگیها چیزی محاسبه میکند و برمیگرداند (چاپ نمیکند):
class Circle:
def __init__(self, radius):
self.radius = radius
def area(self):
pi = 3.14159
return pi * (self.radius ** 2)
c = Circle(10)
result = c.area()
print(result)توجه کنید:
- متد
areaمقدار را برمیگرداند، نه اینکه چاپ کند. - این به شما انعطاف بیشتری میدهد: میتوانید از مقدار در محاسبات دیگر هم استفاده کنید.
تمرینهای پیشنهادی
برای تمرینِ ویژگیها و متدها، میتوانید این ایدهها را پیاده کنید:
- کلاس
Student - ویژگیها:
name،grade(نمره) - متدها:
show_info()برای چاپ نام و نمرهis_passed()که اگر نمره بالای ۱۰ بودTrueبرگرداند وگرنهFalse.- کلاس
Dog - ویژگیها:
name،age - متدها:
bark()که یک جمله مثل"Woof! من Rex هستم"چاپ کند.get_human_age()که سن سگ را مثلا در ۷ ضرب کند و مقدار را برگرداند.- کلاس
Counter - ویژگی:
value - متدها:
increment()که مقدار را یک واحد زیاد کند.reset()که مقدار را صفر کند.show()که مقدار فعلی را چاپ کند.
در این تمرینها تلاش کنید:
- تفاوت بین دادهها (ویژگیها) و رفتارها (متدها) را واضح نگه دارید.
- تا حد امکان همهی ویژگیهای مهم را در
__init__تعریف کنید. - در متدها همیشه از
selfبرای دسترسی به ویژگیها استفاده کنید.