الثلاثاء، 24 ديسمبر 2019

البرمجة كائنية التوجه في بايثون بيثون Python Object Oriented

البرمجة كائنية التوجه في بايثون بيثون 

Python  Object Oriented

البرمجة كائنية التوجه في بايثون بيثون Python  Object Oriented

بيثون كانت لغة كائنية التوجه منذ وجودها.  وبسبب هذا ، فإن إنشاء واستخدام الطبقات والكائنات سهل تمامًا.  يساعدك هذا الفصل في أن تصبح خبيرًا في استخدام دعم البرمجة بايثون الموجه.

 إذا لم يكن لديك أي خبرة سابقة في البرمجة الموجهة للكائنات (OO) ، فقد ترغب في الرجوع إلى دورة تمهيدية حولها أو على الأقل تعليمي من نوع ما بحيث يكون لديك فهم للمفاهيم الأساسية.

 ومع ذلك ، إليك مقدمة صغيرة عن البرمجة الموجهة للكائنات (OOP) لتجلب لك السرعة -

Overview of OOP Terminology

نظرة عامة على مصطلحات OOP
  • Class − الفئة 
  • نموذج أولي معرف من قبل المستخدم لكائن يحدد مجموعة من السمات التي تميز أي كائن من الفئة.  السمات هي أعضاء البيانات (متغيرات الفئة ومتغيرات المثيل) وطرق الوصول إليها عبر تدوين النقاط.
  • Class variable − متغيرات الفئة 
  • متغير يتم مشاركته بواسطة كل نسخ الفئة.  يتم تعريف متغيرات الفصل داخل الفصل ولكن خارج أي من طرق الفصل.  لا يتم استخدام متغيرات الفئة بشكل متكرر مثل متغيرات المثيل.
  • Data member − عناصر البيانات
  • متغير فئة أو متغير مثيل يحتفظ بالبيانات المرتبطة بفئة وكائناتها.
  • Function overloading − دالة الحمل الزائد
  • تعيين أكثر من سلوك لوظيفة معينة.  تختلف العملية المنفذة باختلاف أنواع الكائنات أو الوسائط المعنية.
  • Instance variable −متغير مثيل - 
  • متغير يتم تعريفه في أحد الأساليب وينتمي فقط إلى المثيل الحالي لفئة.
  • Inheritance − الوراثة .
  • نقل خصائص الفئة  إلى فئات أخرى مشتقة منه
  • Instance −المثيل
  • كائن فردي لفئة معينة.  كائن الكائنات الذي ينتمي إلى دائرة فئة ، على سبيل المثال ، هو مثيل للدائرة الفئة.
  • Instantiation −  المثيل المنشىء
  • إنشاء مثيل لفئة.
  • Method −  الدالة 
  • نوع خاص من الوظائف يتم تعريفه في تعريف الفئة.
  • Object −  الكائن 
  • مثيل فريد لهيكل البيانات الذي تم تعريفه بواسطة فئته.  يشتمل الكائن على أعضاء البيانات (متغيرات الفئة ومتغيرات المثيل) والأساليب.
  • Operator overloading − المشغل الزائد 
  • تخصيص أكثر من وظيفة لمشغل معين.

Creating Classes انشاء الفئة 

عبارة class تنشيء تعريف فئة جديد.  اسم الفئة يتبع مباشرة فئة الكلمة الأساسية متبوعة بنقطتين كما يلي -
class ClassName:
   'Optional class documentation string'
   class_suite
  • يحتوي الفصل على سلسلة وثائق ، والتي يمكن الوصول إليها عبر ClassName .__ doc__.

     يتكون class_suite من جميع عبارات المكون التي تحدد أعضاء الفصل وسمات البيانات والوظائف.

مثال Example

فيما يلي مثال لفئة بيثون البسيطة -
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
  • المتغير empCount هو متغير فئة يتم تقاسم قيمته بين جميع مثيلات الفئة.  يمكن الوصول إلى هذا كـ Employee.empCount من داخل الفصل أو خارج الفصل.

     الطريقة الأولى __init __ () هي طريقة خاصة ، والتي تسمى مُنشئ الفئة  أو طريقة التهيئة التي تستدعي Python عند إنشاء مثيل جديد لهذه الفئة.

     تقوم بتعريف دوال الفئة  الأخرى مثل الدوال العادية مع استثناء أن الوسيطة الأولى لكل طريقة ذاتية.  بيثون تضيف المتغير الوسيط  الذاتية إلى القائمة بالنسبة لك ؛  لا تحتاج إلى تضمينه عند استدعاء الدوال.

Creating Instance Objects إنشاء كائنات مثيل

لإنشاء مثيلات لفئة ما ، يمكنك استدعاء الفصل باستخدام اسم الفصل وتمرير أي وسيطات يقبلها أسلوب __init__.
"This would create first object of Employee class"
emp1 = Employee("Zara", 2000)
"This would create second object of Employee class"
emp2 = Employee("Manni", 5000)

Accessing Attributes الوصول للصفات

يمكنك الوصول إلى سمات الكائن باستخدام مشغل نقطة مع كائن.  سيتم الوصول إلى متغير الفئة باستخدام اسم الفئة على النحو التالي -
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'

Built-In Class Attributes الصفات المدمجة في الفئة 

تحتفظ كل فئة من فئات Python بسمات مضمنة ويمكن الوصول إليها باستخدام عامل التشغيل 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':
, 'empCount': 2, 
'displayEmployee': , 
'__doc__': 'Common base class for all employees', 
'__init__': }

Destroying Objects (Garbage Collection) تدمير او إزالة الكائنات مجموعة النفايات 

يقوم Python بحذف الكائنات غير الضرورية (أنواع مدمجة أو مثيلات فئة) تلقائيًا لتحرير مساحة الذاكرة.  العملية التي بواسطتها تقوم Python باسترداد كتل الذاكرة التي لم تعد قيد الاستخدام بشكل دوري تسمى Garbage Collection.

 يعمل جامع البيانات المهملة من Python أثناء تنفيذ البرنامج ويتم تشغيله عندما يصل عدد مرجع الكائن إلى الصفر.  يتغير عدد مرجع الكائن كعدد الأسماء المستعارة التي تشير إلى التغييرات.

 يزيد عدد مرجع الكائن عندما يتم تعيين اسم جديد له أو وضعه في حاوية (قائمة أو مجموعة حروف أو قاموس).  يتناقص عدد مرجع الكائن عند حذفه باستخدام del ، أو يتم إعادة تعيين المرجع الخاص به ، أو عندما يكون مرجعه خارج النطاق.  عندما يصل عدد مرجع كائن إلى الصفر ، يقوم Python بجمعه تلقائيًا.
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 __ () ، والتي تسمى المدمرة ، والتي يتم استدعاءها عندما يكون المثيل على وشك التدمير.  يمكن استخدام هذه الطريقة لتنظيف أي موارد بخلاف الذاكرة تستخدم بواسطة مثيل.

 مثال
 يقوم المدمر __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 = pt1
print id(pt1), id(pt2), id(pt3) # prints the ids of the obejcts
del pt1
del pt2
del pt3
ملاحظة - من الناحية المثالية ، يجب عليك تحديد فئاتك في ملف منفصل ، ثم يجب عليك استيرادها إلى ملف البرنامج الرئيسي الخاص بك باستخدام عبارة الاستيراد.
المخرجات 
3083401324 3083401324 3083401324
Point destroyed

فئات الوراثة Class Inheritance

بدلاً من البدء من نقطة الصفر ، يمكنك إنشاء فصل عن طريق اشتقاقه من فصل موجود مسبقًا عن طريق إدراج الفئة الأصل بين قوسين بعد اسم الفئة الجديد.

 يرث الفصل التابع سمات الفئة الأصل الخاصة به ، ويمكنك استخدام هذه السمات كما لو كانت محددة في الفصل الفرعي.  يمكن للفصل الفرعي أيضًا تجاوز أعضاء البيانات والأساليب من الأصل.

الصيغة Syntax

يتم الإعلان عن الفئات المشتقة إلى حد كبير مثل فئة الآباء.  ومع ذلك ، يتم إعطاء قائمة بالفئات الأساسية الموروثة منها بعد اسم الفئة -
class SubClassName (ParentClass1[, ParentClass2, ...]):
   'Optional class documentation string'
   class_suite

مثال Example


#!/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 class B
.....

class C(A, B):   # subclass of A and B
.....
يمكنك استخدام دالات issubclass () أو isinstance () للتحقق من العلاقات بين فئتين ومثيلات.

 ترجع الدالة المنطقية issubclass (sub، sup) صوابًا إذا كانت subclass subclass المعطى بالفعل فئة فرعية من suplclass sup.

 ترجع الدالة المنطقية isinstance (obj ، Class) إلى true إذا كانت obj هي مثيل للفئة Class أو هي مثيل لفئة فرعية من Class

Overriding Methods دوال إعادة القيادة او التجاوز 

يمكنك دائمًا تجاوز أساليب الفصل الأصل.  أحد أسباب تخطي أساليب الوالدين هو أنك قد ترغب في وظائف خاصة أو مختلفة في فئتك الفرعية.

مثال Example


#!/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

Base Overloading Methods

يسرد الجدول التالي بعض الوظائف العامة التي يمكنك تجاوزها في الفصول الدراسية الخاصة بك -
Sr.No.الدالة والوصف وطريقة الاستدعاء 
1
__init__ ( self [,args...] )
Constructor (with any optional arguments)
Sample Call : obj = className(args)
2
__del__( self )
تدمير ، حذف الكائن 
Sample Call : del obj
3
__repr__( self )
تمثيل سلسلة قابلة للتقييم
Sample Call : repr(obj)
4
__str__( self )
تمثيل سلسلة للطباعة
Sample Call : str(obj)
5
__cmp__ ( self, x )
مقارنة الكائن
Sample Call : cmp(obj, x)

Overloading Operators مشغلي التحميل الزائد

−افترض أنك قمت بإنشاء فئة Vector لتمثيل متجهات ثنائية الأبعاد ، ماذا يحدث عند استخدام عامل التشغيل plus لإضافتها؟  على الأرجح سوف يصرخ بيثون عليك.

 ومع ذلك ، يمكنك تحديد طريقة __add__ في الفصل الدراسي الخاص بك للقيام بإضافة متجهية ومن ثم سيتصرف عامل التشغيل الإضافي حسب التوقع

مثال Example


#!/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)

Data Hiding إخفاء البيانات

قد تكون أو لا تكون سمات الكائن مرئية خارج تعريف الفئة.  تحتاج إلى تسمية السمات ببادئة تسطير سفلي مزدوج ، ثم لا تكون تلك السمات مرئية بشكل مباشر للغرباء.

مثال Example


#!/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
المخرجات
2
Traceback (most recent call last):
   File "test.py", line 12, in 
      print counter.__secretCount
AttributeError: JustCounter instance has no attribute '__secretCount'

تحمي Python هؤلاء الأعضاء عن طريق تغيير الاسم داخليًا لتضمين اسم الفصل.  يمكنك الوصول إلى سمات مثل object._className__attrName.  إذا كنت ستستبدل السطر الأخير كما يلي ، فهذا مناسب لك -
.........................
print counter._JustCounter__secretCount

المخرجات  
1
2
2

التسميات: