الهدف:
هو لمجرد التعرّف على كيفية بناء صنف class يحتوي على خصائص خاصة Private و على كيفية عمل خاصية التعيين setter و خاصية الجلب getter. و هذه المفاهيم تصب في مفهوم برمجي يتعلق بالبرمجة الكائنية OOP و تُسمى هندسياً بـ تغيلف البيانات Data Encapsulation أو بالأحرى و بخصوصية اكتر نستطيع أن نقول هذا الدرس هو حول إخفاء البيانات و التفاصيل data hiding.
الدرس مناسب جداً لمن لديهم خلفية مسبقة عن Python و عن هذه الآليات و المفاهيم من لغات و تجارب مع لغات أخرى. هذا يعني أنني متوقعة بعض الإلمام المسبق لهذه المفاهيم و خصوصاً هي مفاهيم بسيطة و ابتدائية و لكن نريد أن نتعرف عليها في لغة python و تحديداً النسخة التالتة. (زكية كتير هالـ python)...
ضيفتنا في هذا الدرس:
هي النقطة Point و هي عبارة عن صنف سنقوم بإنشائها تحتوي على ميزات النقطة المعروفة حسابية و هي القيم المحورية x و y. و هذه ليست إلا خصائص properties لأي نقطة ذات بعدين بالعالم.
الصنف Point:
حسناً نستطيع إنشاء هالصنف ببساطة كالتالي:
- >>> class Point():
- def __init__(self, x = 0, y = 0):
- self.x = x # خاصية المحور (إكس)
- self.y = y # خاصية المحور (واي)
قمنا بتعيين قيم استهلالية للخاصية x,y بصفر لكل منهن. كما هو واضح في القيم الممررة إلى دالة الإنشاء __init__. و نستطيع من ثم بكل بساطة من تعيين هذه القيم لاحقاً أو قراءتهن كالتالي:
- >>> p = Point() #إنشاء نقطة ببساطة
- >>> p.x
- 0
- >>> p.y
- 0
- >>> p.x = 10
- >>> p.x
- 10
- >>> # كزلك نفس الطريقة بالنسبة لـ واي
و لكن هذه الطريقة ليست نموزجية برمجياً. لأن الخاصية x و y مكشوفة للمستخدم و يتستطيع عمل تعديلات عليهن و التصريف فيهن دون قيود او شروط... لذلك نقوم بإنشاء تلك الخصائص على أنها خاصة و لايمكن قراتهن او تعديلهن مباشرة و يتم زلك بواسطة إضافة شرطيتين سفلية double underscores (__) قبل اسم x و y.
و تكون الصنف Point كالتالي بعد لعملنا التعديل:
- >>> class Point():
- def __init__(self, x = 0, y = 0):
- self.__x = x #نلاحظ الشرطتين قبل الخاصية إكس
- self.__y = y # و هنا ايضاً قبل الخاصية واي
ولكن! الآن لا نستطيع ان نقوم بقراءة او تعيين هالخصائص كما فعلنا سابقاً و سينتج البرنامج اخطاء استسنائية لو حاولنا زلك:
- >>> p = Point()
- >>> p.__x
- Traceback (most recent call last):
- File "<pyshell#42>", line 1, in <module>
- p.__x
- AttributeError: 'Point' object has no attribute '__x'
- >>> p.__y
- Traceback (most recent call last):
- File "<pyshell#43>", line 1, in <module>
- p.__y
- AttributeError: 'Point' object has no attribute '__y'
- >>>
(كزابة هالـ python)
بتقول برسالة الأخطاء أنه لا يوجد خاصية __y أو __x!!! و الحقيقة هي خاصة private ...
خاصية التعيين و الجلب getter|setter:
الآن ما رأيكم لو قمنا بإنشاء خصائص بواسطتهن نقرأ و نكتب على تلك الخصائص و بنفس الوقت تكون خاصة private؟
هنا يأتي دور مفهوم setter و getter و هني عبارة عن دوال عادية تقوم بالوصول إلى تلك الخصائص x و y و تقرأهن و تكتب عليهن. ببساطة نعمل تعديل (إضافة) كالتالي:
- >>> class Point():
- def __init__(self, x = 0, y = 0):
- self.__x = x
- self.__y = y
- def getX(self): #دالة الجلب لقراءة إكس
- return self.__x
- def getY(self): #دالة الجلب لقراءة واي
- return self.__y
- def setX(self, x): # دالة التعيين لتعيين قيمة إكس
- # Typically we have to write a pre-condition here
- self.__x = x
- def setY(self, y): # لتعيين قيمة واي
- # Typically we have to write a pre-condition here
- self.__y = y
و هنا نستعمل تلك الدوال بشكل طبيعي:
- >>> p = Point()
- >>> p.getX() # نداء لدالة الجلب لقراءة إكس
- 0
- >>> p.setY(10) #نداء التعيين لتعيين قيمة اجديدة لـ واي
- >>> p.getY() # لقراءة قيمة واي الجديدة
- 10
- >>>
الجميل بالموضوع الخاصية Decorator:
الآن ما رأيكم لو نتخلص من كلمة get و set و الأقواس و تعبئتهن داخل تلك الأقواس هكزا:
- >>> p = Point()
- >>> p.x
- 0
- >>> p.y = 10
- >>> p.y
- 10
حسناً هناك كلمات بسيطة نضيفهن قبل دوال الجلب و التعيين getters و setters تمكننا من كتابة الشيفرة السابقة بدون أي مشاكل و بنفس الوقت x و y في القسم الخاص private. و تكون الصنف Point بعد لعملنا التعديل و بشكلا النهائي كالتالي:
- >>> class Point():
- def __init__(self, x = 0, y = 0):
- self.__x = x
- self.__y = y
- @property
- def x(self):
- return self.__x
- @property
- def y(self):
- return self.__y
- @x.setter
- def x(self, x):
- # Typically we have to write a pre-condition here
- self.__x = x
- @y.setter
- def y(self, y):
- # Typically we have to write a pre-condition here
- self.__y = y
كل كلمة تبدأ بحرف (الآت) @ هي عبارة عن Decorator. نلاحظ ايضاً أن لخصائص الجلب getter نكتب الكلمة property. و لخصائص التعيين setter نكتب إسم الدالة و نقطة متبوعة بكلمة setter. و هنا python ستتعرف عليهن لاحقاً و ستهتم بباقي الأمر سواء تقرأ (تجلب) او تعيين بواسطة اسم الدالة مباشرة علامة = كما هو واضح بالتطبيق التالي:
- >>> p = Point()
- >>> p.x
- 0
- >>> p.y
- 0
- >>> p.x = 10
- >>> p.x
- 10
- >>> p.y = 10
- >>> p.y
- 10
- >>>
آسفة للإطالة...كنت عم بقص الوقت بالموضوع
معجبة اكتير بهالفكرة الزكية
موفقين يارب
bye
خيتكم رغــد
