في الكود الذي قدمته، يظهر بوضوح بعض السوء في فهمك لاستخدام المتغيرات في الكلاسات في لغة البرمجة بايثون. دعني أشرح لك كيف يتم التعامل مع المتغيرات في الكلاسات والكائنات (الانسنستس) في بايثون.
أولاً وقبل كل شيء، دعنا نناقش الاختلاف بين المتغيرات التابعة للكلاس (class variables) والمتغيرات التابعة للكائن (instance variables). المتغيرات التابعة للكلاس تكون مشتركة بين جميع الكائنات التي تستند إلى الكلاس، بينما تكون المتغيرات التابعة للكائن فريدة لكل كائن.
في الكود الذي قدمته، المتغير energy
هو متغير كلاس، لكن الطريقة التي تقوم بها بتعديل قيمته داخل الدوال (work
) تجعله يبدو كمتغير تابع للكائن. عندما تقوم بتغيير قيمة energy
باستخدام self.energy -= 1
، فإنك تقوم بإنشاء نسخة جديدة من المتغير energy
محددة للكائن الذي قمت بالتعديل عليه، وبالتالي تظهر الفروق في القيم بين الكائنين a1
و a2
.
أما المتغير skills
، فهو مشترك بين جميع الكائنات لأنك قمت بتعريفه خارج الدوال وليس داخل __init__
، ولهذا يتم مشاركته بين جميع الكائنات. يجب أن تكون حذرًا عند تعريف قائمة أو أي هيكل بيانات آخر كمتغير كلاس، حيث يمكن أن يؤدي ذلك إلى نتائج غير متوقعة كما هو الحال هنا.
لتصحيح هذا، يمكنك تعديل الكود كما يلي:
pythonclass Animal(object):
def __init__(self):
self.energy = 10
self.skills = []
def work(self):
print('I do something')
self.energy -= 1
def new_skill(self, skill):
self.skills.append(skill)
if __name__ == '__main__':
a1 = Animal()
a2 = Animal()
a1.work()
print(a1.energy) # النتيجة: 9
print(a2.energy) # النتيجة: 10
a1.new_skill('bark')
a2.new_skill('sleep')
print(a1.skills) # النتيجة: ['bark']
print(a2.skills) # النتيجة: ['sleep']
بتحديد energy
و skills
داخل __init__
، ستتأكد من أنها تعتبر الآن متغيرات تابعة للكائن، وليس متغيرات كلاس، وبالتالي ستظهر السلوك المتوقع للبرنامج.
المزيد من المعلومات
بالطبع، دعنا نستمر في توسيع فهمنا حول مفهوم المتغيرات في الكلاسات والكائنات في لغة البرمجة بايثون.
عند إنشاء كائن من الكلاس، يتم استدعاء الدالة __init__
تلقائياً إذا كانت موجودة. هذه الدالة تُستخدم لتهيئة الكائن وتعيين القيم الابتدائية للمتغيرات التابعة له. في الكود السابق، تم استخدام __init__
لتعيين قيمة ابتدائية لمتغيري energy
و skills
:
pythondef __init__(self):
self.energy = 10
self.skills = []
هذا يعني أن كل مرة تقوم فيها بإنشاء كائن جديد من الكلاس Animal
، ستتم إعادة تهيئة المتغيرات energy
و skills
بقيمها الابتدائية. هذا يضمن أنه عند بدء كل كائن بقيمة معينة لـ energy
و skills
.
من المهم أن نفهم أيضاً أنه يمكننا تعريف المتغيرات في أي وقت داخل الكلاس، وليس فقط داخل __init__
. على سبيل المثال، يمكننا إضافة متغير آخر للكلاس Animal
:
pythonclass Animal(object):
total_animals = 0 # متغير كلاس
def __init__(self):
self.energy = 10
self.skills = []
Animal.total_animals += 1 # زيادة قيمة المتغير الكلاس عند إنشاء كائن جديد
هنا تم تعريف متغير total_animals
كمتغير كلاس، ويتم زيادة قيمته في __init__
عند إنشاء كائن جديد.
لفهم أفضل للمفاهيم المتقدمة، يمكنك النظر إلى مواضيع مثل التركيبات (composition)، الوراثة (inheritance)، والطبقات الفرعية (subclasses) في لغة البرمجة بايثون، وكيف يمكن استخدامها لبناء تركيبات أكثر تعقيدًا وفعالية في البرمجة الشيئية.