فهم متغيرات الأصناف والنسخ في بايثون 3
بايثون، كأحد أشهر لغات البرمجة في العالم، توفر للمطورين مجموعة واسعة من الأدوات والميزات التي تتيح لهم كتابة برامج مرنة، فعالة وسهلة الفهم. ومن بين هذه الميزات المهمة التي تشكل قلب العديد من التطبيقات هي التعامل مع المتغيرات والأصناف (Classes) والنسخ (Instances). يعتبر فهم كيفية عمل المتغيرات داخل الأصناف والنسخ في بايثون أمرًا حيويًا لمطورين مبتدئين ومتقدمين على حد سواء. سنحاول في هذا المقال تقديم شرح مفصل حول هذه المتغيرات وطريقة عمل النسخ في بايثون 3.
الأصناف (Classes) في بايثون
الأصناف في بايثون هي قالب يُستخدم لإنشاء الكائنات (objects) التي تمثل مفاهيم معينة في البرمجيات. تحتوي الأصناف على متغيرات (المعروفة أيضًا بالخصائص أو السمات) ودوال (تسمى بالطرق أو الـ Methods) التي تحدد سلوك هذه الكائنات. في بايثون، يمكن تعريف صنف باستخدام الكلمة المفتاحية class.
لنأخذ مثلاً صنفًا بسيطًا يمثل سيارة:
pythonclass Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def display_info(self):
return f"{self.year} {self.make} {self.model}"
في هذا المثال، قمنا بتعريف صنف يسمى Car يحتوي على:
-
الخصائص:
make,model,year، وهي متغيرات تحمل معلومات حول السيارة. -
الطريقة:
display_infoالتي تعرض معلومات السيارة.
النسخ (Instances) في بايثون
عندما يتم إنشاء كائن من صنف معين، يتم إنشاء “نسخة” من هذا الصنف. هذه النسخة، أو الكائن، تحمل البيانات الخاصة بها ويمكن التفاعل معها بشكل مستقل عن الكائنات الأخرى. تُعتبر النسخ هي الوحدات الأساسية التي يتم التعامل معها في البرمجة الكائنية.
يمكن إنشاء نسخة من الصنف Car كما يلي:
pythonmy_car = Car("Toyota", "Corolla", 2020)
print(my_car.display_info())
هنا، my_car هو نسخة من الصنف Car، وهي تحتوي على بيانات خاصة بها (مثل العلامة التجارية والطراز والسنة). يتم استدعاء طريقة display_info باستخدام الكائن my_car لطباعة المعلومات.
المتغيرات داخل الأصناف والنسخ
في بايثون، يمكن تقسيم المتغيرات داخل الأصناف إلى نوعين رئيسيين: المتغيرات المثيلة و المتغيرات الذاتية.
المتغيرات المثيلة (Class Variables)
المتغيرات المثيلة هي متغيرات تُعرّف على مستوى الصنف نفسه. هذه المتغيرات مشتركة بين جميع النسخ (الكائنات) التي تم إنشاؤها من هذا الصنف. يُمكن تعديلها من خلال الصنف نفسه أو من خلال النسخ، ولكنها ستؤثر على جميع النسخ.
على سبيل المثال، يمكن إضافة متغير مثيل إلى الصنف Car يمثل عدد السيارات التي تم تصنيعها:
pythonclass Car:
total_cars = 0
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
Car.total_cars += 1
def display_info(self):
return f"{self.year} {self.make} {self.model}"
في هذا المثال، total_cars هو متغير مثيل، وهو يشير إلى العدد الإجمالي للسيارات التي تم إنشاؤها باستخدام الصنف Car. كلما تم إنشاء سيارة جديدة، يزيد هذا العدد.
المتغيرات الذاتية (Instance Variables)
المتغيرات الذاتية هي متغيرات تُعرّف داخل دالة __init__ وتكون مرتبطة بكل نسخة على حدة. يتم الوصول إليها باستخدام self، مما يجعل كل نسخة تمتلك نسخة مستقلة من هذه المتغيرات.
في المثال السابق، المتغيرات make, model, و year هي متغيرات ذاتية. كل نسخة من الصنف Car تحتوي على قيم مختلفة لهذه المتغيرات.
النسخ المتغيرات وعمليات النسخ (Copying Instances)
في بعض الأحيان، قد يحتاج المطور إلى إنشاء نسخة من كائن موجود بالفعل. بايثون يوفر طرقًا مختلفة لإنشاء نسخ من الكائنات سواء كانت شاملة أو ضحلة.
النسخ الضحل (Shallow Copy)
النسخ الضحل يعني إنشاء نسخة جديدة من الكائن الذي يحتوي فقط على النسخة الأساسية من البيانات. في حالة إذا كان الكائن يحتوي على متغيرات من أنواع معقدة مثل القوائم أو القواميس، فإن النسخة الضحلة ستنسخ هذه الأنواع كمرجع بدلاً من نسخ البيانات نفسها.
pythonimport copy
car1 = Car("Honda", "Civic", 2022)
car2 = copy.copy(car1)
هنا، car2 هو نسخة ضحلة من car1. إذا كان داخل car1 متغير يحتوي على قائمة أو قاموس، فسيتم نسخ المرجع لهذه المتغيرات بدلاً من نسخ القيم نفسها.
النسخ العميق (Deep Copy)
النسخ العميق، على عكس النسخ الضحل، يقوم بإنشاء نسخة كاملة من الكائن، بما في ذلك نسخ الكائنات المعقدة داخله. وهذا يعني أن التغييرات التي تطرأ على النسخة العميقة لن تؤثر على النسخة الأصلية.
pythoncar1 = Car("Ford", "Focus", 2021)
car2 = copy.deepcopy(car1)
في هذه الحالة، car2 هو نسخة عميقة من car1، ويحتوي على نسخة مستقلة تمامًا من جميع البيانات الموجودة في car1.
تفاوت بين النسخ والمراجع في بايثون
من المهم أن نفهم الفرق بين النسخ والمراجع في بايثون. في بايثون، عندما نقوم بتمرير كائن كوسيلة إلى دالة، نمرر المرجع إلى الكائن، وليس نسخة مستقلة منه. لذلك، أي تعديل يتم على الكائن داخل الدالة سيؤثر على الكائن الأصلي.
pythondef modify_car(car):
car.year = 2023
my_car = Car("Chevrolet", "Malibu", 2020)
modify_car(my_car)
print(my_car.year) # ستتم طباعة 2023
في المثال السابق، modify_car تقوم بتغيير سنة my_car إلى 2023، ويؤثر ذلك مباشرة على الكائن الأصلي.
الخاتمة
في بايثون، يعد فهم كيفية عمل المتغيرات والأصناف والنسخ من الأساسيات التي يجب على كل مبرمج إتقانها. إن المعرفة بتفاصيل هذه المفاهيم يتيح للمطورين كتابة أكواد أكثر كفاءة وقوة في البرمجة الكائنية. مع فهمك الجيد لكيفية إنشاء الأصناف والنسخ، بالإضافة إلى طرق التعامل مع المتغيرات داخل هذه الأصناف، ستتمكن من بناء تطبيقات مرنة وقابلة للتطوير تتفاعل بذكاء مع البيانات.

