مفهوم الوراثه في بايثون
في بايثون، يمكن استخدام مفهوم الوراثة لإنشاء تركيبات أكثر تعقيدًا من الأشياء التي هي بالفعل موجودة. يتيح لنا الوراثة إنشاء فئة جديدة تستفيد من الصفات والسلوكيات الموجودة في فئة أخرى.
على سبيل المثال، إذا كان لدينا فئة "حيوان" تتضمن الصفات الأساسية للحيوانات، يمكننا إنشاء فئات فرعية مثل "كلب" أو "قطة" التي ترث كافة الخصائص الأساسية للحيوان، بالإضافة إلى بعض الخصائص الفريدة لتلك الفئات الفرعية.
لتعريف فئة ترث من فئة أخرى في بايثون، يمكن استخدام الكلمة المفتاحية "class" وتحديد اسم الفئة الفرعية، ثم تحديد اسم الفئة الأم التي ترث منها، مثل هذا المثال:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("Subclass must implement abstract method")
class Dog(Animal):
def speak(self):
return "Woof"
class Cat(Animal):
def speak(self):
return "Meow"
في هذا المثال، يحتوي الفئة "Animal" على الخاصية "name" والطريقة "speak". تعتبر طريقة "speak" طريقة افتراضية مجردة ترجع خطأ إذا لم يتم تنفيذها في الفئات الفرعية. ترث الفئات "Dog" و "Cat" من الفئة الأم "Animal" وتحويان على طرق "speak" فريدة ترجع كل منها قيمة نصية مختلفة.
اشكال الوراثه في بايثون
يمكن استخدام عدة أشكال لتمثيل الوراثة في Python، ومن أهمها:
- الإرث المتعدد (Multiple inheritance):
مثال:
class A:
def method_A(self):
print("This is method A from class A")
class B:
def method_B(self):
print("This is method B from class B"
class C(A, B):
def method_C(self):
print("This is method C from class C")
object_C = C()
object_C.method_A() # Output: This is method A from class A
object_C.method_B() # Output: This is method B from class B
object_C.method_C() # Output: This is method C from class C
- الإرث الفرعي (Single Inheritance):
مثال:
class A:
def method_A(self):
print("This is method A from class A")
class B(A):
def method_B(self):
print("This is method B from class B")
object_B = B()
object_B.method_A() # Output: This is method A from class A
object_B.method_B() # Output: This is method B from class B
- الإرث الوهمي (Mixin Inheritance):
مثال:
class MyMixin:
def mixin_method(self):
print("This is a mixin method")
class MyClass(MyMixin):
def my_class_method(self):
print("This is a class method")
object_MyClass = MyClass()
object_MyClass.my_class_method() # Output: This is a class method
object_MyClass.mixin_method() # Output: This is a mixin method
دوال جاهزة في بايثون يمكن إستخدامها لمعرفة طبيعة العلاقة بين كلاس و آخر أو بين كائن و آخر.
في بايثون، يمكن استخدام دالة type() لمعرفة نوع الكائن. ولمعرفة طبيعة العلاقة بين كلاسين أو بين كائنين، يمكن استخدام دالة isinstance() .
دالة type() تستخدم لمعرفة نوع الكائن. على سبيل المثال، إذا كان لديك متغير x ، يمكنك استخدام
type(x)
لمعرفة نوعه. ستعيد هذه الدالة اسم النوع مثل int أو str .
أما دالة isinstance() فتستخدم لمعرفة ما إذا كان الكائن من نوع معين أم لا. على سبيل المثال، إذا كان لديك متغير x ، يمكنك استخدام isinstance(x, int) لمعرفة ما إذا كان x من نوع int أم لا. ستعيد هذه الدالة True إذا كان x من نوع int و False إذا لم يكن.
وبشكل عام، يمكن استخدام هذه الدوال لمعرفة طبيعة العلاقة بين كائنين أو بين كلاسين. على سبيل المثال، يمكنك استخدام type() لمعرفة نوع الكائنات واستخدام isinstance() للتحقق من ما إذا كانت تنتمي إلى نفس النوع أو لا.
دالة isinstance()
دالة isinstance() هي دالة مدمجة في لغة بايثون وتستخدم للتحقق من نوع الكائن (object) المحدد. تأخذ هذه الدالة كمدخلين الكائن الذي تريد التحقق من نوعه والنوع الذي تريد التحقق منه.
في حالة أن الكائن ينتمي إلى النوع المحدد، فإن الدالة تعيد قيمة True، وإلا فإنها تعيد قيمة False.
على سبيل المثال، إذا أردنا التحقق ما إذا كانت قيمة معينة عبارة عن عدد صحيح (integer)، يمكن استخدام الدالة بهذه الطريقة:
x = 5
if isinstance(x, int):
print("x is an integer")
else:
print("x is not an integer")
سيتم طباعة "x is an integer" بالنسبة للقيمة 5، لأنها عدد صحيح.
دالة issubclass
دالة issubclass في بايثون تستخدم للتحقق ما إذا كانت الفئة (class) هي مشتقة من فئة أخرى.
إذا كانت الفئة المحددة مشتقة من الفئة المعطاة، فإن الدالة تعود قيمة True . وإلا، تعود قيمة False .
تستخدم الدالة على النحو التالي:
issubclass(class, classinfo)
حيث:
- - class : الفئة التي سيتم التحقق من اشتقاقها.
- - classinfo : الفئة التي يجب التحقق ما إذا كانت الفئة class مشتقة منها. يمكن أن تكون قائمة تحتوي على فئات متعددة.
على سبيل المثال، إذا كنت تريد التحقق ما إذا كانت فئة ChildClass مشتقة من فئة ParentClass ، فيمكن استخدام الدالة على النحو التالي:
class ParentClass:
pass
class ChildClass(ParentClass):
pass
print(issubclass(ChildClass, ParentClass)) # True
تضارب الأسماء عند وراثة أكثر من كلاس بايثون
يتعلق تضارب الأسماء في وراثة أكثر من كلاس في لغة بايثون بحدوث تضارب في اسم المتغيرات التي تم تعريفها في الكلاسات الفرعية والأساسية. عندما يحدث هذا التضارب، فإن Python يمنع إجراءات البرمجة التي تتعارض مع الأسماء المتعارضة.
ومن أجل حل تضارب الأسماء، يمكن استخدام المسافة الأسماء (namespace) الخاصة بكل كلاس. وبالتالي يمكن تجنب تضارب الأسماء عن طريق استخدام الـ namespace الخاص بكل كلاس وتحديد الفئة المطلوبة عن طريق الـ namespace الخاص بها.
على سبيل المثال، إذا كان لدينا كلاسان يحملان نفس الاسم "MyClass"، يمكننا استخدام الـ namespace لكل منهما لتحديد الفئة المطلوبة عند الاستدعاء، كما يلي:
class MyClass:
def __init__(self):
self.var = "Base Class"
class MyClass2(MyClass):
def __init__(self):
super().__init__()
self.var = "Derived Class"
mc1 = MyClass()
mc2 = MyClass2()
print(mc1.var) # Output: Base Class
print(mc2.var) # Output: Derived Class
في هذا المثال، يتم استخدام الـ namespace لكلاس MyClass في الفئة الأساسية والفئة المشتقة باستخدام super().__init__() للوصول إلى الـ namespace الخاص بها وتقديم قيمة مختلفة للمتغير var .
حل مشكلة تضارب الأسماء عند وراثة أكثر من كلاس
يمكن حل مشكلة تضارب الأسماء عند وراثة أكثر من كلاس في بايثون باتباع إحدى الطرق التالية:
- استخدام اسم مختلف للفئة الموروثة:
- استخدام فضاء الأسماء (namespace):
- استخدام دالة super():
- استخدام اسم متغير:
على سبيل المثال، يمكن استخدام الطريقة التالية:
class BaseClass:
def __init__(self):
self.name = "Base Class"
class SubClass(BaseClass):
def __init__(self):
super().__init__()
self.subname = "Sub Class"
obj = SubClass()
print(obj.name)
print(obj.subname)
في هذا المثال، يتم استخدام دالة super() للوصول إلى الأسماء الموروثة من الفئة الأساسية، مما يحل مشكلة التضارب في الأسماء.
الكلاس object في بايثون
يعد الـ class في Python هو قالب يستخدم لإنشاء أشياء جديدة، ويعتبر الـ object في Python هو كلاس رئيسي يمكن استخدامه كقالب أساسي لإنشاء أي كلاسات جديدة.
بالإضافة إلى ذلك، تُعتبر جميع الكائنات في Python مشتقة من الـ class object، بمعنى أنه يتم تكوين كل كائن في Python عن طريق نسخ سمات وصفات الـ class object.
ويتضمن الـ class object بعض الميثودز المهمة مثل:
- - __init__ : هذا الميثود يعتبر الميثود البنائي Constructor و يتم استخدامه لإعداد الكائن بالقيم الأولية.
- - __str__ : هذا الميثود يُستخدم لتحويل الكائن إلى string.
- - __del__ : هذا الميثود يعتبر Destructor و يتم استخدامه لإزالة الكائن عندما لا يعد هناك مرجع إليه.
وعلى الرغم من أنه يمكن إنشاء كلاس جديد في Python دون الاعتماد على الكلاس الرئيسي object، إلا أن استخدامه يساعد في ضمان توافق التراث بين الكلاسات وتبسيط البرمجة.