تتميز لغة البرمجة بايثون باللغة غرضية التوجه منذ البدايات ولذلك فإن إنشاء الصفوف والأغراض تعتير عملية سهلة وفي هذا القسم سيتعلم المستخدم كيفية استخدام الدعم الذي تقدمه لغة البرمجة بايثون غرضية التوحه.
التالي هو مقدمة للبرمجة غرضية التوجه.
مراجعة لمصطلحات البرمجة غرضية التوجه
- الصف: هو نموذج يتم تعريفه من قبل المستخدم لغرض ما والذي يعرف مجموعة من السمات التي تصف أي غرض من الصف وهذه السمات يمكن ان تكون بيانات وطرق.
- متحول الصف: وهو المتحول الذي تتم مشاركته من كافة المساحات ضمن الصف ويتم تعريف هذا المتحول ضمن الصف لكن خارج طرق الصف.
- عضو البيانات: متحول الصف أو متحول المسافة التي تضبط البيانات المجتمعة مع الصف وأغراضها.
- تابع التحميل الزائد: إسناد أكثر من مفهوم أو مهمة للتابع الخاص وتختلف هذه العملية المنجزة باختلاف نماذج الأغراض أو المدخلات المتضمنة.
- متحول المسافة: المتحول الذي يتم تعريفه ضمن الطريقة ويعود حصراً لمسافة الصف الحالية.
- الوراثة: وتعني نقل المميزات من صف إلى صف آخر مشتق منه.
- المسافة: الأغراض المستقلة لصف محدد.
- المثيل: تحديد مسافة الصف.
- الطريقة: تعرف خاص للتابع المعرف في تعريف الصف.
- الغرض: مسافة مميزة من تركيبة البيانات والمعرفة ضمن صفها.
- مشغل التحميل الزائد: إسناد أكثر من تابع إلى مشغل خاص.
إنشاء الصفوف
تستخدم التعليمة class لإنشاء صفوف جديدة وتعريفها ويتم وضع اسم الصف كالتالي:
class ClassName: 'Optional class documentation string' class_suite
- للصف سلسلة وثائق والتي يمكن الوصول إليها عن طريق __doc__ .
- تتألف الـ class_suite من كافة التعليمات المعرفة كأعضاء للصف وسمات البيانات والتوابع.
مثال
class Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary
إنشاء أغراض المسافة
لإنشاء مسافة ما ضمن الصف يجب استدعاء الصف باستخدام اسم الصف وإسناد المدخلات.
"This would create first object of Employee class" emp1 = Employee("Zara", 2000) "This would create second object of Employee class" emp2 = Employee("Manni", 5000)
الوصول إلى السمات
يتم الوصول إلى سمات الأغراض باستخدام المشغل dot مع الغرض ويتم الوصول إلى متحول الصف باستخدام اسم الصف كالتالي –
emp1.displayEmployee() emp2.displayEmployee() print "Total Employee %d" % Employee.empCount
والآن عند وضع كافة المفاهيم سوية:
#!/usr/bin/python class Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary "This would create first object of Employee class" emp1 = Employee("Zara", 2000) "This would create second object of Employee class" emp2 = Employee("Manni", 5000) emp1.displayEmployee() emp2.displayEmployee() print "Total Employee %d" % Employee.empCount
فتظهر النتيجة التالية:
Name: Zara,Salary: 2000 Name: Manni,Salary: 5000 Total Employee 2
ويمكن إضافة سمة الجمع والإزالة والتعديل للصف والأغراض –
emp1.age = 7 # Add an 'age' attribute. emp1.age = 8 # Modify 'age' attribute. del emp1.age # Delete 'age' attribute.
يمكن استخدام التوابع التالية بدلاً من استخدام التعليمات الاعتيادية :
- التابع
getattr(obj, name[, default])
: للوصول إلى سمة الغرض. - التابع
hasattr(obj,name)
:لاختبار فيما إذا كانت السمة موجودة أم لا. - التابع
setattr(obj,name,value)
لضبط السمة إذا كانت غير موجود وبعدها يتم إنشاؤها. التابعdelattr(obj, name)
: لحذف السمة.
hasattr(emp1, 'age') # Returns true if 'age' attribute exists getattr(emp1, 'age') # Returns value of 'age' attribute setattr(emp1, 'age', 8) # Set attribute 'age' at 8 delattr(empl, 'age') # Delete attribute 'age'
سمات الصفوف المبنية
جميع السبات في بايثون لها السمات التالية ويمكن الوصول إليها باستخدام المشغل dot مثل أي سمة أخرى-
- __dict__ : القاموس الحاوي على الفراغات الاسمية للصف.
- __doc__ : سلسلة الصف أو لاشيئ إذا كانت غير معرفة.
- __name__ : اسم الصف.
- __module__ : اسم الوحدة التي تم تعريف الصف عندها وهذه السمة تقابل السمة "__main__" في النمط التفاعلي.
- __bases__ : الصف الفارغ المحتمل والحاوي على الصف الأساسية وفق تراتبية حدوثها في قائمة الصف الأساسية.
ومن أجل الصف السابق يمكن استخدام كافة السمات –
#!/usr/bin/python class Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary print "Employee.__doc__:", Employee.__doc__ print "Employee.__name__:", Employee.__name__ print "Employee.__module__:", Employee.__module__ print "Employee.__bases__:", Employee.__bases__ print "Employee.__dict__:", Employee.__dict__
فتظهر النتيجة التالية
Employee.__doc__: Common base class for all employees Employee.__name__: Employee Employee.__module__: __main__ Employee.__bases__: () Employee.__dict__: {'__module__': '__main__', 'displayCount': <function displayCount at 0xb7c84994>, 'empCount': 2, 'displayEmployee': <function displayEmployee at 0xb7c8441c>, '__doc__': 'Common base class for all employees', '__init__': <function __init__ at 0xb7c846bc>}
تدمير الكائنات
تقوم لغة البرمجة بايثون بحذف الأغراض التي لاحاجة لها بشكل تلقائي وذلك لتوفير مساحة ضمن الذاكرة وتسمى هذه العملية بجمع النفايات حيث يبدأ جامع النفايات خلال عملية تنفيذ البرنامج ويتوقف عندما يصل العداد المرجعي للغرض المنفذ إلى الصفر.
يزداد هذا العداد عندما عندما يسند له اسم جديد او عند وضعه في مكان جديد مثل (قائمة أو صف أو قاموس). ويتناقص عندما يتم حذفه باستخدام التعليمة del ويعاد إسناد المرجع للعداد أو يخرج خارج التنفيذ وعندما يصل للصفر فإن بايثون تقوم بجمعه تلقائياً.
a = 40 # Create object <40> b = a # Increase ref. count of <40> c = [b] # Increase ref. count of <40> del a # Decrease ref. count of <40> b = 100 # Decrease ref. count of <40> c[0] = -1 # Decrease ref. count of <40>
تقوم هذه الأداة __del__() بطباعة اسم الصف للمسافة التي هي على وشك الإزالة-
#!/usr/bin/python class Point: def __init( self, x=0, y=0): self.x = x self.y = y def __del__(self): class_name = self.__class__.__name__ print class_name, "destroyed" pt1 = Point() pt2 = pt1 pt3 = pt1print id(pt1), id(pt2), id(pt3) # prints the ids of the obejcts del pt1del pt2del pt3
فتظهر النتيجة التالية
308340132430834013243083401324 Point destroyed
توريث الصف
بدلاً من إنشاء صف جديد فإنه من الممكن اشتقاق صف من صف آخر موجود مسبقاً وذلك بوضع الصف الجديد بين قوسين بعد اسم الصف الجديد.
يتم توريث كافة سمات الصف الأصلي للصف الوليد ويمكن استخدام هذه السمات مع الصف الجديد كما لو أنها أنشئت ضمنه وكذلك الأمر بالنسبة للطرق والبيانات.
الشيفرة البرمجية
class SubClassName (ParentClass1[, ParentClass2, ...]): 'Optional class documentation string' class_suite
مثال
#!/usr/bin/python class Parent: # define parent class parentAttr = 100 def __init__(self): print "Calling parent constructor" def parentMethod(self): print 'Calling parent method' def setAttr(self, attr): Parent.parentAttr = attr def getAttr(self): print "Parent attribute :", Parent.parentAttr class Child(Parent): # define child class def __init__(self): print "Calling child constructor" def childMethod(self): print 'Calling child method' c = Child() # instance of child c.childMethod() # child calls its method c.parentMethod() # calls parent's method c.setAttr(200) # again call parent's method c.getAttr() # again call parent's method
فتظهر النتيجة التالية
Calling child constructor Calling child method Calling parent method Parent attribute : 200
وبشكل مشابه يمكن اشتقاق صف من صفوف متعددة كالتالي-
class A: # define your class A ..... class B: # define your calss B ..... class C(A, B): # subclass of A and B .....
يمكن استخدام التابع issubclass() أو التابع isinstance() لتفحص العلاقات بين صفين أو مسافتين.
- التابع issubclass(sub, sup)يعيد القيمة صح إذا كان الصف الفرعي المعطىsub فعلاً صفاً فرعياً للصف sup .
- التابع isinstance(obj, Class)يعيد القيمة صح إذا كان obj مسافة للصف أوClassأو مسافة للصف الفرعي للصف.
تجاهل الطرق
يمكن زيادة التحميل بالنسبة لطرق الصفوف لعدة أسباب أهمها الحاجة لوجود توابع خاصة أو مختلفة في الصف الفرعي.
مثال
#!/usr/bin/python class Parent: # define parent class def myMethod(self): print 'Calling parent method' class Child(Parent): # define child class def myMethod(self): print 'Calling child method' c = Child() # instance of child c.myMethod() # child calls overridden method
فتظهر النتيجة التالية
Calling child method
تجاهل المشغلات
لنفترض إنشاء صف Vector لتمثيل شعاعين ثنائيي البعد. ماذا سيحدث لو حاول المشغل إضافة الجمع إليهما؟!
يمكن للمستخدم تعريف الطريقة __add__في الصف لإنجاز عملية جمعوبعدها يسلك المشغل الخاص بالجمع سلوكاً مسبق التوقع.
مثال
#!/usr/bin/python class Vector: def __init__(self, a, b): self.a = a self.b = b def __str__(self): return 'Vector (%d, %d)' % (self.a, self.b) def __add__(self,other): return Vector(self.a + other.a, self.b + other.b) v1 = Vector(2,10) v2 = Vector(5,-2) print v1 + v2
فتظهر النتيجة التالية
Vector(7,8)
تخبئة البيانات
يمكن أن تكون سمات الغرض ظاهرة أو غير ظاهرة خارج تعريف الصف ولجعل هذه السمات غير ظاهرة خارج تعريف الصف يتم تسميتها بوضع خطين سفليين قبلها ( __ ).
مثال
#!/usr/bin/python class JustCounter: __secretCount = 0 def count(self): self.__secretCount += 1 print self.__secretCount counter = JustCounter() counter.count() counter.count() print counter.__secretCount
فتظهر النتيجة التالية
1 2 Traceback (most recent call last): File "test.py", line 12, in <module> print counter.__secretCountAttributeError: JustCounter instance has no attribute '__secretCount'
تقوم لغة البرمجة بايثون بحماية هذه الأعضاء من خلال التغيير الداخلي للاسم ليتضمن اسم الصف. ويمكن الوصول إلى هذه السمات مثل object._className__attrName .من الممكن استبدال السطر الأخير كالتالي :
......................... print counter._JustCounter__secretCount
فتظهر النتيجة التالية
1 2 2
ليست هناك تعليقات:
إرسال تعليق