مبانی شیءگرایی
در این درس کلاس میسازید و از آن شیء میسازید، متد __init__ و self را میفهمید و تصمیم میگیرید کجا کلاس و کجا دیکشنری کافی است.
آنچه در این درس میآموزید
- کلاس تعریف کنید و از آن چند شیء بسازید
- متد __init__ و نقش self را در تعریف و فراخوانی تشخیص دهید
- تصمیم بگیرید دادهٔ شما کلاس میخواهد یا دیکشنری کافی است
فهرست مطالب
تا اینجا داده و رفتار جدا بودند: دیکشنری اطلاعات دانشآموز را نگه میداشت و توابعی جداگانه روی آن کار میکردند. شیءگرایی این دو را کنار هم میگذارد. کلاس (Class) قالبی است که میگوید «این نوع داده چه ویژگیهایی دارد و چه کارهایی بلد است»؛ و شیء (Object) نمونهای ساختهشده از آن قالب است. هر بار که در این دوره contact = {"name": "سارا"} نوشتید یا text.strip() صدا زدید، در واقع با کلاس و شیء کار کردهاید؛ حالا نوبت ساختن آنهاست.
کلاس و شیء
کلاس با کلمه کلیدی class تعریف میشود و ساختن شیء از آن مثل فراخوانی تابع است:
class Dog:
def bark(self):
return "Woof woof!"
my_dog = Dog()
print(my_dog.bark())Woof woof!
سطر my_dog = Dog() یک شیء تازه از کلاس میسازد و my_dog.bark() متد (Method) آن شیء را صدا میزند؛ متد یعنی تابعی که به یک شیء وصل است و با نقطه فراخوانی میشود، همان نقطهای که در text.strip() دیده بودید.
متد init و ویژگیها
متد ویژهٔ __init__ هنگام ساختن هر شیء بهطور خودکار اجرا میشود و جای مقدارهای اولیه است:
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
def info(self):
return f"{self.name}: {self.score}"
s = Student("Arash", 18)
print(s.info())
print(s.name)Arash: 18 Arash
هنگام Student("آرش", 18) پایتون متد __init__ را صدا میزند و آرگومانها به name و score میروند. دستور self.name = name ویژگی (Attribute) میسازد: دادهای که داخل خودِ شیء ذخیره میشود و هر جا با نقطه در دسترس است. متد info هم به همین ویژگیها رجوع میکند و رشتهٔ مناسب هر شیء را میسازد.
نقش self
پارامتر self نشاندهندهٔ خودِ همان شیء است که متد رویش صدا زده شده. شما هنگام فراخوانی آن را نمیفرستید؛ پایتون خودش میفرستد:
s.info()در باطن یعنیStudent.info(s)؛ شیءsبه پارامترselfمیرود.- به همین دلیل تعریف هر متد عادی با
selfشروع میشود، ولی فراخوانیاش بدون آرگومان است.
این قرارداد شاید در نگاه اول پرکار بنماید، اما راز دسترسی هر متد به ویژگیهای همان شیء است.
هر شیء حالت خودش را دارد
از یک کلاس هر تعداد شیء میسازید و هر شیء ویژگیهای مستقل خودش را دارد:
class Counter:
def __init__(self):
self.count = 0
def increase(self):
self.count += 1
a = Counter()
b = Counter()
a.increase()
a.increase()
b.increase()
print(a.count)
print(b.count)2 1
دو شیء a و b هر دو از یک قالباند، ولی شمارندهٔ جدا دارند؛ افزایش a هرگز b را نمیلرزاند. متد increase هر بار روی self.count همان شیء کار میکند. این جدایی حالتها دلیل اصلی جان گرفتن کلاس است.
متدهایی که تصمیم میگیرند
متدها فقط نمایشدهندهٔ داده نیستند؛ میتوانند منطق هم داشته باشند:
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
def is_passing(self):
return self.score >= 10
print(Student("Maryam", 17).is_passing())
print(Student("Reza", 8).is_passing())True False
قاعدهٔ قبولی یک بار در کلاس نوشته شده و همهٔ نقاط برنامه از همان یکی پیروی میکنند؛ اگر فردا قاعده عوض شود فقط is_passing تغییر میکند.
پایتون خودش شیء را بهعنوان آرگومان میفرستد و اگر متد جای پذیرفتنش نداشته باشد، شکایت میکند. :::
کلاس یا دیکشنری؟
دادهٔ سادهٔ بدون رفتار را دیکشنری بگیرید؛ {"name": "سارا", "score": 18} کاملاً شرافتمندانه است. اما هرجا توابعی جداگانه و مکرر روی همان داده کار میکنند — اعتبارسنجی، نمایش، مقایسه — کلاس داده و رفتار را یکجا جمع میکند و برنامه مرتب میماند.
تمرینها
تمرین
تمرین ۱ — کلاس Book
کلاسی به نام Book بنویسید که هنگام ساخت دو ویژگی title و pages بگیرد و متدی به نام summary داشته باشد که رشتهای به شکل «کتاب [عنوان] با [تعداد] صفحه» برگرداند؛ سپس یک شیء بسازید و متد را صدا بزنید.
# Write your code hereنمایش راهحل
class Book:
def __init__(self, title, pages):
self.title = title
self.pages = pages
def summary(self):
return f"Book {self.title} has {self.pages} pages"
b = Book("Python", 320)
print(b.summary())Book Python has 320 pages
::: :::
خلاصه
- کلاس قالبِ داده و رفتار است و با فراخوانی نامش، از آن شیء ساخته میشود.
__init__هنگام ساخت شیء اجرا میشود و باself.x = ...ویژگی میسازد.selfخودِ شیء است؛ فراخوانیs.info()یعنیStudent.info(s).- هر شیء ویژگیهای مستقل خودش را دارد؛ تغییر یکی، دیگری را عوض نمیکند.
- دادهٔ بدون رفتار دیکشنری میگیرد؛ داده با رفتارِ تکرارشونده کلاس میخواهد.
در درس پایانی این دوره، مسیر طیشده را مرور میکنیم و برای ادامهٔ یادگیری با پروژههای واقعی و پکیجهای عمومی نقشه میریزیم.