الكلاسات والكائنات في Python
حتى الآن كنت تحفظ بيانات الطالب في قاموس، وتكتب الدوال التي تتعامل معه في مكان آخر. البرمجة الكائنية (Object-Oriented Programming) تجمع البيانات والدوال التي تخصها في مكان واحد. في هذا الدرس ستتعلم الكلاس (Class) والكائن (Object)، وهما أساس أغلب البرامج الكبيرة.
الكلاس والكائن
Section titled “الكلاس والكائن”تخيّل قالب الكعك: القالب نفسه ليس كعكة، لكنك تصنع به كعكات كثيرة، ولكل كعكة طعمها وزينتها. الكلاس هو القالب، والكائنات هي الكعكات.
كلاس Student مثلاً يصف أي طالب: له اسم ودرجة. أما «سارة ودرجتها 95» فهي كائن محدد مصنوع من هذا الكلاس.
class Student: def __init__(self, name, grade): self.name = name self.grade = grade
def introduce(self): print(f"أنا {self.name} ودرجتي {self.grade}")
sara = Student("سارة", 95)omar = Student("عمر", 82)
sara.introduce()omar.introduce()print(sara.name)أنا سارة ودرجتي 95أنا عمر ودرجتي 82سارةلنفهم الكود جزءاً جزءاً:
class Student:تعرّف كلاساً جديداً. جرت العادة أن يبدأ اسم الكلاس بحرف كبير.__init__دالة خاصة تُستدعى تلقائياً عند إنشاء كل كائن، ومهمتها تجهيز بياناته. قبلها وبعدها شرطتان سفليتان.Student("سارة", 95)ينشئ كائناً جديداً، ويرسل القيمتين إلى__init__.self.nameوself.gradeهما خصائص (Attributes) الكائن، أي بياناته المحفوظة داخله.introduceدالة داخل الكلاس، وتسمى تابعاً (Method)، ونستدعيها بالنقطة:sara.introduce().
ما هي self؟
Section titled “ما هي self؟”self هي الكائن نفسه الذي نتعامل معه الآن. عندما تكتب sara.introduce() ترسل Python الكائن sara تلقائياً إلى المعامل self، وعندما تكتب omar.introduce() يكون self هو omar. لذلك طبعت الدالة نفسها اسمين مختلفين.
القاعدة: كل تابع داخل الكلاس يبدأ بالمعامل self، وأنت لا ترسله عند الاستدعاء، فـ Python ترسله عنك.
توابع تغيّر حالة الكائن
Section titled “توابع تغيّر حالة الكائن”قوة الكائنات أنها تحفظ حالتها وتغيّرها بتوابعها. هذا كلاس لحساب بنكي:
class BankAccount: def __init__(self, owner, balance=0): self.owner = owner self.balance = balance
def deposit(self, amount): self.balance += amount
def withdraw(self, amount): if amount > self.balance: print("الرصيد غير كافٍ") return self.balance -= amount
def __str__(self): return f"حساب {self.owner}: {self.balance} جنيه"
account = BankAccount("ليلى", 100)account.deposit(50)account.withdraw(500)account.withdraw(30)print(account)الرصيد غير كافٍحساب ليلى: 120 جنيهلاحظ ثلاثة أشياء:
- المعامل
balance=0له قيمة افتراضية، فيمكن كتابةBankAccount("ليلى")لحساب يبدأ من صفر. - التابع
withdrawيحمي الرصيد: لا يسمح بسحب أكثر من الموجود. هذه ميزة مهمة للكلاسات، فالقواعد تُكتب مرة واحدة في مكان واحد. __str__تابع خاص يحدد النص الذي يظهر عند طباعة الكائن بـprint.
خصائص الكلاس وخصائص الكائن
Section titled “خصائص الكلاس وخصائص الكائن”الخصائص التي نكتبها داخل __init__ بـ self تخص كل كائن وحده. لكن يمكن تعريف خاصية على مستوى الكلاس نفسه، فتكون مشتركة بين كل الكائنات:
class Cat: legs = 4
def __init__(self, name): self.name = name
a = Cat("مشمش")b = Cat("لولو")print(a.legs, b.legs)print(a.name, b.name)4 4مشمش لولوكل القطط لها أربع أرجل، فوضعنا legs في الكلاس. أما الاسم فيختلف من قطة إلى أخرى، فوضعناه في __init__.
كائنات داخل قائمة
Section titled “كائنات داخل قائمة”الكائنات قيم عادية: تضعها في قوائم، وتمر عليها بحلقة، وترسلها إلى الدوال:
students = [Student("سارة", 95), Student("عمر", 82), Student("هدى", 67)]
for student in students: if student.grade >= 80: print(student.name, "متفوق")سارة متفوقعمر متفوقجرّب بنفسك
Section titled “جرّب بنفسك”اكتب كلاساً اسمه Book له ثلاث خصائص: العنوان title، وعدد الصفحات pages، والصفحة الحالية current وتبدأ من صفر. أضف تابعاً read(count) يزيد الصفحة الحالية دون أن تتجاوز عدد الصفحات، وتابعاً __str__ يعرض التقدم:
كتاب الأيام: قرأت 40 من 180 صفحةكتاب الأيام: قرأت 180 من 180 صفحةأخطاء شائعة
Section titled “أخطاء شائعة”- نسيان
selfفي تعريف التابع: إذا كتبتdef introduce():ثم استدعيتsara.introduce()فسترى الخطأTypeError: Student.introduce() takes 0 positional arguments but 1 was given، لأن Python أرسلت الكائن ولم تجد معاملاً يستقبله. - نسيان
self.عند استخدام خاصية: داخل التابع،nameوحدها متغير عادي غير معرّف. اكتبself.name. - كتابة
_init_بشرطة واحدة: لن تعتبرها Python دالة التجهيز. الصحيح شرطتان من كل جهة:__init__. - نسيان الأقواس عند الإنشاء:
sara = Studentلا تنشئ كائناً، بل تجعلsaraاسماً آخر للكلاس.
اختبر نفسك
Section titled “اختبر نفسك”سؤال
متى تُستدعى الدالة __init__؟
__init__ تعمل تلقائياً عند إنشاء كل كائن، وفيها نجهّز خصائصه الأولى.
سؤال
ما الذي يمثله self داخل التابع؟
self هو الكائن الحالي، ولذلك يعطي التابع نفسه نتائج مختلفة مع كل كائن.
الخلاصة
Section titled “الخلاصة”- الكلاس قالب، والكائن نسخة مصنوعة منه لها بياناتها الخاصة.
__init__تجهّز الكائن عند إنشائه، وselfتشير إلى الكائن الحالي.- الخصائص بيانات الكائن، والتوابع دوال تعمل عليها.
__str__تحدد شكل الكائن عند طباعته.- خصائص الكلاس مشتركة بين كل الكائنات، وخصائص
selfخاصة بكل كائن.