مدخل إلى البيانات وأنواعها: أنواع البيانات الأساسية
يحتاج أي عمل إبداعي إلى ثلاثة مكونات أساسية هي: الأدوات التي يُنجَز بها، والخامات التي يتكون منها، والأساليب والتقنيات التي تُستغل الأدوات والخامات بها لإنجاز ذلك العمل، فأدوات الرسم مثلًا هي الفرش والأقلام ولوحات الرسم، كما أن من أساليب الرسم الخلط والرش وغيرها، ثم تأتي الخامات التي هي الدهانات والأوراق والماء ونحو ذلك. وبصورة مماثلة نجد أن أدوات البرمجة هي لغات البرمجة ونظم التشغيل وعتاد الحواسيب التي ستعمل عليها البرامج؛ أما الأساليب والتقنيات فهي هياكل البرامج التي تحدثنا عنها في المقال السابق، والخامات هي البيانات التي نعدل فيها ونعالجها، وهي ما سننظر فيه في هذا المقال.
هذا المقال طويل بسبب طبيعة البيانات نفسها، لكننا كتبناه بحيث لا تجب قراءته كله من أجل إدراك الفهم الكامل للبياناتوتستطيع البدء فيه من البداية التي نمر فيها على الأنواع البسيطة للبيانات.
البيانات Data
من المعلوم بالمشاهدة في عالم البرمجة أن البيانات هي أكثر المصطلحات المستخدمة حاليًا، رغم قلة من يفهمها على حقيقتها، وما يهمنا في هذه السلسلة في موضوع تعريف البيانات نفسها؛ هو أن تعلم أنها الحقائق أو الأرقام التي يمكن استخلاص النتائج والمعلومات المفيدة منها، ورغم أن هذا يكاد يكون تسطيحًا لمفهومها، إلا أنه يعطينا نقطةً نبدأ منها على الأقل، وسنرى فيما يلي إن كنا نستطيع توضيح ذلك بالنظر في كيفية استخدام البيانات في البرمجة.
البيانات هي تلك المعلومات الخام التي يعدّل فيها البرنامج ويغيرها، فلا تستطيع البرامج تنفيذ أي وظيفة ولا مهمة ذات قيمة بغير تلك البيانات، وتتوقف أنواع التعديلات التي تجريها البرامج على البيانات على تلك الأنواع نفسها، فكل نوع له عدد من العمليات التي يمكن إجراؤها عليه، فقد رأينا مثلًا أننا نستطيع جمع الأعداد معًا، إذ تحدث عملية الجمع على النوع العددي من البيانات، مما يعني أن البيانات تأتي في عدة صور وأشكال، وسننظر في كل نوع من أشهر تلك الأنواع، إضافةً إلى العمليات المتاحة على ذلك النوع.
المتغيرات Variables
تخزَّن البيانات في ذاكرة الحواسيب، ويمكن تشبيه تلك الذاكرة بذاكرة مكاتب البريد القديمة، إذ توضع صناديق صغيرة على حوائط تلك المكاتب لتصنيف الرسائل البريدية، ويجب كتابة الوجهة التي تُرسَل إليها رسائل كل صندوق على الصندوق نفسه، إذ لا قيمة للرسائل من دون وجهة تُرسل إليها، وهنا نُسقط مثالنا على البرمجة، إذ إن المتغيرات هي العناوين التي تكتَب على الصناديق داخل ذاكرة الحاسوب.
بهذا نكون قد عرفنا نوع البيانات الآن، لكننا لا نستطيع تعديلها قبل أن تكون لنا صلاحية الوصول إليها، وهذه هي وظيفة المتغيرات، فنحن ننشئ نسخًا من أنواع البيانات ونسندها إلى المتغيرات، والنسخة instance هي مجرد جزء من البيانات وليكن 3 أو 5 مثلًا، وهي نُسخ لأعداد؛ أما المتغير فهو إشارة إلى منطقة محددة في ذاكرة الحاسوب تحتوي على البيانات.
قد تتطلب بعض لغات البرمجة أن يُصرَّح عن المتغير declared ليطابق نوع البيانات التي يشير إليها، فإذا حاولنا إسناد نوع خاطئ من البيانات إليه، فسنحصل على خطأ، ويفضل بعض المبرمجين ذلك النوع المسمى بالكتابة الثابتة static typing، لأنه يحول دون ارتكاب الزلات البرمجية bugs الدقيقة التي يصعب اكتشافها، على أن جميع اللغات التي نستخدمها هنا مرنة إلى الحد الذي نستطيع معه إسناد أي نوع من البيانات إلى المتغيرات، وهو ما يُعرف بالكتابة الديناميكية dynamic typing.
تتبع أسماء المتغيرات قواعدًا محددةً تختلف باختلاف لغة البرمجة التي تستخدمها، فلكل لغة قواعدها للأحرف التي يُسمح أو لا يُسمح بها، كما تشترط بعض اللغات مثل جافاسكربت وبايثون أن ينتبه المبرمج إلى حالة الأحرف التي يكتبها، بحيث تختلف python
عن Python
مثلًا، كما توجد لغات أخرى مثل VBScript لا تهتم لهذا، لكن يفضل أن يُتبَّع أسلوب ثابت في تسمية المتغيرات لتجنب الأخطاء الشائعة عند الانتقال من لغة لأخرى، ومن الأساليب المستخدمة في تسمية المتغيرات هو بدء اسم المتغير بحرف صغير، ثم استخدام حرف كبير لبداية كل كلمة تالية في اسمه، كما يلي:
aVeryLongVariableNameWithCapitalisedStyle
لن نتحدث هنا عن القواعد التي تحكم المحارف المسموح بها في لغات البرمجة التي سنستخدمها، لكن إذا كنت تستخدم الأسلوب الذي في المثال؛ فستجنب نفسك كثيرًا من المشاكل في هذا الشأن. ومن الأساليب المستخدمة في تسمية المتغيرات أيضًا فصل الكلمات في اسم المتغير بشرطة سفلية، كما في another_variable_name
؛ أما في لغة بايثون فيأخذ المتغير نوع البيانات المسندة إليه، ويحتفظ بهذا النوع ويحذرك إذا حاولت خلط البيانات بطرق تختلف عنه، كأن تحاول إضافة سلسلة نصية إلى عدد مثلًا، وهي نفس حالة المثال الذي عرض لنا رسالة الخطأ في المقال السابق، ويمكن تغيير نوع البيانات التي يشير إليها المتغير عن طريق إعادة الإسناد إلى المتغير reassigning.
>>> q = 7 # عددًا الآن q صار >>> print( q ) 7 >>> q = "Seven" # ليكون سلسلة نصية q أعد إسناد >>> print( q ) Seven
لاحظ أن المتغير q
ضُبط ليشير إلى العدد 7
ابتداءً، وقد حافظ على تلك القيمة إلى أن جعلناه يشير إلى سلسلة المحارف "Seven"
، وعلى هذا نستنتج أن متغيرات بايثون تحافظ على النوع الذي تشير إليه، لكننا نستطيع تغيير ذلك عن طريق إعادة الإسناد إلى المتغير، وتلك هي الكتابة الديناميكية التي ذكرناها قبل قليل.
ويمكن التحقق من نوع المتغير باستخدام الدالة type()
كما يلي:
>>> print( type(q) ) <class 'str'>
تُفقد البيانات الأصلية عند إعادة الإسناد، وتمسحها بايثون من الذاكرة ما لم يكن ثمة متغير آخر يشير إليها، وهذا المحو يُعرف باسم جمع المهملات Garbage Collection، والذي يمكن تشبيهه بموظف غرفة البريد الذي يأتي مرةً واحدةً كل فترة ويزيل أي طرود في صناديق البريد لا توجد عليها ملصقات، فإذا لم يستطع العثور على مالك لها أو لم يوجد عنوان على الطرد؛ فسيرميها في المهملات.
لننظر الآن في بعض الأمثلة على أنواع البيانات.
متغيرات جافاسكربت و VBSCript
تختلف جافاسكربت عن أختها VBScript قليلًا في طريقة استخدام المتغيرات، فكلاهما ترى وجوب التصريح عن المتغير قبل استخدامه، وهي خاصية تشترك فيها اللغات المصرَّفة compiled مع اللغات ذات الكتابة الثابتة statically typed، بل حتى في اللغات الديناميكية مثل تلك التي نستخدمها، حيث نستفيد من التصريح عن المتغيرات في حالة حدوث خطأ إملائي عند استخدام متغير، إذ سسيدرك المترجم أن متغيرًا غير معروف قد استُخدم، وسيرفع خطأً؛ أما عيب هذا الأسلوب فهو الحاجة إلى مزيد من الكتابة من قِبل المبرمج.
VBScript
يصرَّح عن المتغير في لغة VBScript باستخدام التعليمة Dim
، وهي اختصار لكلمة Dimension أو بُعد، وهي إشارة إلى الجذور الأولى للغة VBScript في لغة BASIC ولغات التجميع من قبلها، حيث كان يجب علينا إخبار المجمِّع بكمية الذاكرة التي سيستخدمها المتغير -أو أبعاده-، وظل الاختصار موجودًا حتى الآن. ويبدو التصريح عن المتغير في VBScript كما يلي:
Dim aVariable
نستطيع بمجرد التصريح عن المتغير أن نعين قيمًا له كما فعلنا في بايثون، ويمكن التصريح عن عدة متغيرات في تعليمة Dim
واحدة بسردها جميعًا مع فصلها بفواصل إنجليزية ","
كما يلي:
Dim aVariable, another, aThird
ويبدو الإسناد بعدها كما يلي:
aVariable = 42 another = "هذه جملة قصيرة." aThird = 3.14159
قد نرى كلمةً مفتاحيةً أخرى هي Let
، وهي من جذور BASIC أيضًا، لكننا لن نراها إلا نادرًا لقلة الحاجة إليها، وهي تُستخدم كما يلي:
Let aVariable = 22
ولن نستخدمها على أي حال في هذه السلسلة.
جافاسكربت
نستطيع التصريح عن المتغيرات مسبقًا في جافاسكربت باستخدام الكلمة var
، كما يمكن التصريح عن عدة متغيرات كما في VBScript في تعليمة var
واحدة:
var aVariable, another, aThird;
كما تسمح جافاسكربت بتهيئة -أو تعريف- المتغيرات مثل جزء من تعليمة var
، كما يلي:
var aVariable = 42; var another = "A short phrase", aThird = 3.14159;
يوفر هذا قليلًا من وقت الكتابة، لكنه لا يختلف عن أسلوب VBScript مع المتغيرات والمكون من خطوتين. يمكن التصريح عن متغيرات جافاسكربت وتهيئتها من غير استخدام var
، بنفس الطريقة المتبعة في بايثون:
aVariable = 42;
غير أن المتعصبين لجافاسكربت يرون أن استخدام var
أفضل، لذا سيكون هذا أسلوبنا في هذه السلسلة أيضًا.
نأمل أن تكون تلك النبذة المختصر عن متغيرات جافاسكربت وVBScript قد أوضحت الفرق بين التصريح عن المتغيرات وبين تعريفها، أما متغيرات بايثون، فتعريفها يعني ضمنيًا التصريح عنها كذلك.
أنواع الكتابة: صارمة أم متغيرة أم ثابتة
لقد أشرنا إلى الكتابة الثابتة والديناميكية فيما سبق من المقال، وتوجد أنواع أخرى من الكتابة مثل الكتابة الصارمة strict -أو القوية أحيانًا أخرى-، والكتابة الفضفاضة loose أو الضعيفة، وسنحاول هنا أن نوضح الاختلافات بينها.
تُنشأ المتغيرات مثل أنواع بيانات مرنة أو ثابتة، ويقال أن النوع الثابت مكتوب كتابةً ثابتةً أي أنه لا يتغير أبدًا-، أما المتغير الذي قد يشير إلى عدة أنواع من البيانات فيُكتب ديناميكيًا، لذا تشير البيانات الثابتة والديناميكية إلى أنواع البيانات التي يمكن تخزينها داخل المتغير. ويمكن دمج المتغيرات في العمليات المختلفة عند البرمجة، حيث ستتطلب كل عملية احتواء متغيراتها على أنواع بعينها، مثل الأعداد أو المحارف، فإذا رفضت اللغة السماح لعملية ما باستخدام أنواع خاطئة؛ فسيقال أن هذا النوع من الكتابة كتابةٌ صارمة.
تحاول بعض اللغات إجبار القيم على الأنواع الصالحة المسموح بها، بينما تسمح لغات أخرى بأي نوع ثم تفشل العملية وتخرِج خطأً، وتلك هي الكتابة الفضفاضة، وعلى هذا تشير كل من الكتابة الصارمة والفضفاضة إلى أسلوب التحقق من أنواع المتغيرات المستخدَمة في العمليات، وبالنسبة للغات التي سنستخدمها في هذه السلسلة، فجميعها تستخدم كتابةً ديناميكيةً قويةً.
الأنواع الأساسية للبيانات
تسمى أنواع البيانات الأساسية primitive data types بهذا الاسم لأنها أبسط أنواع البيانات التي يمكن معالجتها والتعامل معها، أما الأنواع الأعقد من البيانات فما هي في الواقع إلا تجميعات من الأنواع الأساسية، فهي اللبنات الأساسية التي تكوَّن منها جميع الأنواع الأخرى، وبناءً عليه تكون هي أساس الحوسبة كلها، وتشمل الأنواع الأساسية الأرقام والأحرف ونوعًا آخر اسمه النوع البولياني boolean type.
سلاسل المحارف Strings
لقد رأينا هذه السلاسل من قبل، وهي أي سلسلة من المحارف التي يمكن طباعتها على الشاشة، وقد توجد فيها محارف تحكم لا تُطبع ولا تُرى على الشاشة.
تُعرض تلك السلاسل في صورة أحرف، لكن الحاسوب يخزنها في صورة تسلسلات من الأرقام، ويطلق على ربط تلك الأرقام بالمحارف اسم الترميز encoding، وتوجد العديد من الترميزات المختلفة، رغم أن المنتشر حاليًا منها هو واحد من ثلاثة ترميزات معرَّفة بواسطة معيار الترميز الموحد Unicode Standard، وسننظر في الترميز الموحد أو اليونيكود في مقال لاحق، لكن يجب أن تعلم أن غرضه توفير مخطط ترميز يمثل أي حرف من أي أبجدية في أي مكان في العالم، إضافةً إلى المحارف الخاصة التي تحتاجها الحواسيب مثل الأقواس والتحكم والتهريب وغيرها. لن نعير هذا الترميز كثير الانتباه أثناء العمل، لكن قد نحتاج إلى التحويل بين الرموز الرقمية والأحرف، كما في مشكلة الاقتباسات في مثال VBScript من المقال السابق.
ويمكن تمثيل السلاسل النصية في بايثون بعدة طرق:
- باستخدام علامات اقتباس مفردة:
'هذه سلسلة نصية'
- أو باستخدام علامات اقتباس مزدوجة:
"وهذه سلسلة نصية تشبهها"
- أو بعلامات اقتباس ثلاثية مزدوجة:
""" أما هذه فسلسلة نصية أطول ونستطيع إطالتها وتقسيمها على ما نشاء من الأسطر وستحافظ بايثون على هذه الأسطر """
يُستخدم النوع الأخير في إنشاء توثيقات لدوال بايثون التي ننشئها بأنفسنا كما سنرى في مقال تال، ويمكن استخدام علامات اقتباس ثلاثية مفردة، لكننا لا ننصح بهذا، إذ قد يصعب تحديد ما إذا كانت العلامات ثلاثيةً مفردةً أم علامةً مزدوجةً داخل أخرى مفردة.
نستطيع الوصول إلى المحارف المنفردة في السلسلة النصية بمعاملتها مثل مصفوفة من المحارف -انظر المصفوفات أدناه-، كما توجد بعض العمليات التي توفرها لغة البرمجة لتساعدنا في التعامل مع السلاسل، مثل العثور على سلسلة فرعية أو ربط سلسلتين معًا، ونسخ واحدة إلى أخرى، وهكذا.
تجدر الإشارة إلى أن بعض اللغات فيها نوع منفصل للمحارف، أي لحرف واحد فقط، وفي تلك الحالة تكون السلاسل مجرد مجموعات من قيم تلك الأحرف، لكن بايثون -على نقيض هذا-ـ إذ تستخدم سلسلةً طولها وحدة واحدة لتخزين الحرف الواحد، ولا يلزم وجود صياغة خاصة.
العوامل النصية String Operators
توجد عدة عمليات يمكن إجراؤها على السلاسل النصية، وبعضها مضمّن مسبقًا في بايثون، لكن يمكن توفير عمليات إضافية باستخدام الوحدات المستورَدة كما فعلنا مع وحدة sys
في المقال السابق حول التسلسلات البسيطة.
العامل | الوصف |
---|---|
S1 + S2 | ضم كل من S1 و S2 |
S1 * N | تكرار قدره N من S1 |
يمكننا أن نرى ذلك في الأمثلة التالية:
>>> print( 'Again and ' + 'again' ) # ضم السلسلة Again and again >>> print( 'Repeat ' * 3 ) # تكرار السلسلة Repeat Repeat Repeat >>> print( 'Again ' + ('and again ' * 3) ) # '*' جمع '+' و Again and again and again and again
كما يمكن إسناد سلاسل أحرف إلى متغيرات:
>>> s1 = 'Again ' >>> s2 = 'and again ' >>> print( s1 + (s2 * 3) ) Again and again and again and again
لاحظ أن المثالين الأخيرين أنتجا نفس الخرج.
هناك الكثير من الأمور التي يمكن تنفيذها باستخدام السلاسل النصية، وسننظر فيها بتفصيل في مقالات تالية بعد أن نكتسب خبرةً جيدةً في المواضيع التي تسبقها.
ربما تجب ملاحظة أن السلاسل النصية في بايثون لا يمكن تعديلها، أي أننا نستطيع إنشاء سلسلة نصية جديدة مع تغيير بعض الأحرف، لكن لا يمكن تعديل أي حرف داخل سلسلة تعديلًا مباشرًا، ويُعرف نوع البيانات ذاك الذي لا يمكن تغييره باسم النوع غير القابل للتغير immutable.
متغيرات السلاسل النصية في VBScript
تسمى المتغيرات في VBScript باسم المتغايرات variants، لأنها قد تحتوي على أي نوع من البيانات، وتحاول VBScript أن تحولها إلى النوع المناسب وفق الحاجة، وعليه فقد نسند عددًا إلى متغير ما، لكن إذا استخدمناه مثل سلسلة نصية فستحاول VBScript أن تحوله نيابةً عنا، وهذا يشبه -من الناحية العملية- سلوك أمر print
في بايثون، غير أنه هنا يمتد إلى أي أمر VBSCript. ويمكن إعطاء VBScript لإشارة على أننا نريد قيمةً عدديةً في صورة سلسلة نصية من خلال تغليفها بعلامتي اقتباس مزدوجتين:
<script type="text/vbscript"> MyString = "42" MsgBox MyString </script>
يمكن دمج سلاسل VBScript معًا في عملية تسمى بالضم concatenation، باستخدام العامل &
:
<script type="text/vbscript"> MyString = "Hello" & "World" MsgBox MyString </script>
سلاسل جافاسكربت النصية
تحاط سلاسل جافاسكربت النصية بعلامات اقتباس مفردة أو مزدوجة، ويجب أن نصرّح عن المتغيرات قبل استخدامها، وذلك بكلمة var
المفتاحية. في المثال التالي سنصرح عن متغيري سلاسل نصية ونعرّفهما:
<script type="text/javascript"> var aString, another; aString = "Hello "; another = "World"; document.write(aString + another); </script>
كما تسمح لنا جافاسكربت بإنشاء كائنات سلاسل نصية، ويمكن القول بأنها سلاسل نصية مع بعض المزايا الإضافية، والاختلاف الرئيسي بينهما هو طريقة إنشائها، والتي هي بالشكل:
<script type="text/javascript"> var aStringObj, anotherObj; aStringObj = String("Hello "); anotherObj = String("World"); document.write(aStringObj + anotherObj); </script>
قد تكون تلك كتابةً كثيرةً قياسًا على المثال السابق مع أنهما ينجزان العمل نفسه -وهذا صحيح نوعًا ما-، غير أن كائنات السلاسل تعطينا مزايا في بعض المواقف تجعلنا نفضل استخدامها عما سواها، كما سنرى لاحقًا.
الأعداد الصحيحة Integers
الأعداد الصحيحة هي الأعداد الكاملة غير الكسرية، من أكبر قيمة سالبة إلى أكبر قيمة موجبة، وهذا التحديد لمجال القيم مهم في البرمجة على عكس الرياضيات، إذ لا نعير اهتمامًا لقيمة العدد غالبًا طالما ينتمي إلى مجموعة أساسية أو المجموعة التي نعمل عليها، أو لم يكن يؤثر في الناتج؛ أما في البرمجة فهناك حدود عظمى وحدود دنيا، ويعرَف الحد الأعلى باسم MAXINT، كما يعتمد على عدد البتات bits المستخدَمة في حاسوبك لتمثيل عدد ما. يكون في أغلب الحواسيب ولغات البرمجة الحالية العدد 64-بت في المعماريات الحديثة، لذا فإن قيمة الحد الأعلى هنا MAXINT تساوي 10 مرفوعة إلى الأس 19، وتستطيع بايثون إخبارنا بقيمة maxint باستخدام وحدة sys
، فإذا كانت معمارية النظام 64-بت مثلًا فستكون قيمة sys.maxsize
هي 9223372036854775807
، وهو رقم كبير؛ أما في VBScript فتكون تلك القيمة محدودةً بـ (+/- 32000) لأسباب تاريخية.
تُعرَف الأعداد التي تحمل إشارةً موجبةً أو سالبةً بالأعداد الصحيحة ذات الإشارة signed integers، ومن الممكن استخدام أعداد صحيحة لا إشارة لها، غير أن هذا مقصور على الأعداد الموجبة، بما في ذلك الصفر، وهذا يعني أن الأعداد الصحيحة التي لا إشارة لها ضعف عدد ذوات الإشارة، بما أننا سنستغل المساحة التي كانت مخصصةً للأعداد السالبة لضمها إلى الأعداد التي لا إشارة لها، مما يعني زيادة قيمة الحد الأقصى إلى الضعف أيضًا "2 * MAXINT"، ونظرًا لأن حجم الأعداد الصحيحة مقيد بقيمة MAXINT، فإذا جمعنا عددين صحيحين وكان ناتج الجمع أكبر من الحد الأقصى؛ فسنحصل على خطأ، لكن قد تعيد بعض الأنظمة واللغات تلك القيمة الخاطئة كما هي مع رفع راية سرية secret flag نستطيع التحقق من وجودها إذا كنا نشك في الإجابة، وفي مثل هذه الحالة يكون التحقق عادةً هو برفع حالة خطأ، فإما أن يكون البرنامج حينها قادرًا على معالجة ذلك الخطأ فيعالجه، أو ينهي البرنامج نفسه إذا لم يستطع.
تحوّل كل من جافاسكربت وVBScript العدد إلى صيغة تستطيعان التعامل معها، ولا تهتمان بالدقة هنا، إذ قد تختلف الصيغة الجديدة اختلافًا طفيفًا؛ أما لغة بايثون فتستخدم شيئًا اسمه العدد الصحيح الطويل Long Integer، وهي ميزة خاصة لها تسمح بأعداد صحيحة غير محدودة الحجم.
>>> import sys >>> x = sys.maxsize * 1000000 >>> print(x) 9223372036854775807000000 >>> print (type(x)) <class 'int'>
كما نرى فالنتيجة أكبر بكثير من القيمة التي تتوقعها من الحاسوب في العادة، رغم احتسابها int
، أما إذا استخدمنا شيفرةً مكافئةً لهذا المثال في جافاسكربت وVBScript؛ فسيخرج لنا العدد بصيغة تختلف عن العدد الصحيح الذي نتوقعه، وسنتعلم المزيد عن هذا في قسم الأعداد الحقيقية.
<script type="text/vbscript"> Dim x x = 123456700 * 34567338738999 MsgBox CStr(x) </script>
العمليات الحسابية
رأينا معظم العمليات الحسابية التي نحتاج إليها في المقال السابق في التسلسلات البسيطة، ولكن للتلخيص نعيدها مرةً أخرىً:
مثال العامل | الوصف |
---|---|
M + N | جمع M و N |
M - N | طرح N من M |
M * N | ضرب M في N |
M / N | قسمة M على N، سيكون الناتج عددًا حقيقيًا كما سنبين لاحقًا |
M // N | القسمة الصحيحة لـ M على N، ستكون النتيجة عددًا صحيحًا |
M % N | باقي القسمة: أوجد ما تبقى من قسمة M على N |
M**N | الأس: M مرفوعًا إلى الأس N |
بما أننا لم نرى المتغير الأخير من قبل، فلننظر في مثال على إنشاء بعض متغيرات الأعداد الصحيحة ونستخدم عامل الأس:
>>> i1 = 2 # i1 أنشئ عددًا صحيحًا وأسنده إلى >>> i2 = 4 >>> i3 = i1**i2 # i3 أسند نتيجة 2 إلى أس 4 إلى >>> print( i3 ) 16 >>> print( 2**4 ) # أكد النتيجة 16
تحتوي الوحدة math
في بايثون على بعض الدوال الرياضية الشائعة مثل sin
و cos
وغيرهما.
عوامل الاختصار
إحدى العمليات الشائعة في البرمجة هي زيادة قيمة المتغير التدريجية، فإذا كان لدينا المتغير x
الذي قيمته 42
، ونريد زيادة تلك القيمة إلى 43
، فسيكون ذلك كما يلي:
>>> x = 42 >>> print( x ) >>> x = x + 1 >>> print( x )
لاحظ السطر التالي:
x = x + 1
لا معنىً لهذا السطر من حيث المنطق الرياضي، لكنه في البرمجة يعني أن x
الجديدة تساوي قيمة x
السابقة مضافًا إليها 1
، فإذا كنت معتادًا على المنطق الرياضي؛ فستستغرق بعض الوقت لتعتاد على هذا النمط الجديد، لكن الفكرة هنا أن علامة =
تُقرأ "ستكون" وليست "تساوي"، وعليه فإن السطر يعني أن x ستصبح قيمتها الجديدة هي x+1، وهذا النوع من العمليات شائع جدًا في الممارسة العملية إلى حد أن بايثون وجافاسكربت توفران عاملًا مختصرًا له من أجل توفير الكتابة على المبرمج:
>>> x += 1 >>> print( x )
وهذان العاملان مساويان تمامًا لتعليمة الإسناد السابقة لكنهما أقصر، توجد عوامل اختصار لباقي العمليات الحسابية بنفس المنطق السابق، نبينها في الجدول التالي:
مثال العامل | الوصف |
---|---|
M += N | M = M + N |
M -= N | M = M - N |
M *= N | M = M * N |
M /= N | M = M / N |
M //= N | M = M // N |
M %= N | M = M % N |
الأعداد الصحيحة في VBScript
لقد قلنا إن الأعداد الصحيحة في VBScript محدودة بقيمة عظمى أقل من بايثون وجافاسكربت، وهي تقابل 16-بت على خلاف 64-بت التي رأيناها من قبل، أي حوالي "+/- 32000"، فإذا احتجنا إلى عدد صحيح أكبر من هذا؛ فنستخدم العدد long
الذي يساوي حجمه حجم العدد الصحيح من معمارية 32-بت (أي 2 مليار)، كذلك لدينا النوع byte
الذي هو عدد ثماني البتات، وحجمه الأكبر يساوي 255، وسيتضح بالممارسة العملية أن النوع القياسي للعدد الصحيح كافٍ لأغلب العمليات، فإذا كانت نتيجة العملية أكبر من MAXINT؛ فستحول VBSCript النتيجة تلقائيًا إلى عدد ذي فاصلة عائمة أو حقيقي، كما سنبين لاحقًا.
ورغم دعم VBScript لجميع العمليات الحسابية المعتادة، إلا أن عملية الباقي modulo تمثَّل تمثيلًا مختلفًا، باستخدام العامل MOD
، وقد رأينا ذلك في فصل التسلسلات البسيطة، كذلك فإن تمثيل الأسس مختلف، إذ يُستخدم محرف الإقحام ^
بدلًا من **
في بايثون.
أعداد جافاسكربت
تحتوي جافاسكربت على نوع عددي في صورة كائن كما سنصفه فيما بعد، وهي تسميه Number، لكن أحيانًا قد يكون عدد جافاسكربت "ليس عددًا" أو Not a Number، ويشار إليه بـ NaN اختصارًا، وهو ما نحصل عليه أحيانًا كنتيجة لبعض العمليات المستحيلة رياضيًا، والهدف منه هو السماح لنا بالتحقق من أنواع أخطاء بعينها دون تعطيل البرنامج، كما تحوي لغة بايثون كذلك النوع NaN أيضًا.
تحتوي جافاسكربت على نسخ عددية خاصة لتمثيل اللانهاية الموجبة والسالبة، وهي ميزة نادرة نسبيًا في لغات البرمجة، وقد تكون كائنات جافاسكربت العددية إما أعدادًا صحيحةً أو حقيقيةً كما سنرى لاحقًا، وتَستخدم جافاسكربت نفس العوامل التي تستخدمها بايثون، باستثناء الإجراءات الأسية التي تستخدم كائنًا خاصًا بها اسمه Math
.
الأعداد الحقيقية Real Numbers
الأعداد الحقيقية هي نفسها الأعداد الصحيحة لكن مع إضافة الكسور، وقد تمثل أعدادًا أكبر من الحد الأقصى MAXINT لكن مع دقة أقل، وهذا يعني أننا قد نرى عددين حقيقيين على أنهما متطابقين، لكن الحاسوب يراهما غير متطابقين عندما يوازنهما معًا، لأنه ينظر في أدق التفاصيل بينهما، حيث يمكن تمثيل العدد 5.0 في الحاسوب بإحدى الصورتين 4.9999999 أو (5.000000…01) مثلًا، وهذه التقاربات مناسبة لأغلب الاستخدامات، لكن قد نحتاج أحيانًا إلى تلك الدقة، فتذكر هذا الأمر إذا حصلت على نتيجة غريبة لا تتوقعها عند استخدام الأعداد الحقيقية.
كما تُعرَف الأعداد الحقيقية أيضًا باسم أعداد الفاصلة العائمة floating point numbers، ولها نفس العمليات الحسابية التي تطبّق على الأعداد الصحيحة، مع زيادة هنا وهي قدرتها على اقتطاع العدد ليكون قيمة صحيحة.
تدعم لغات البرمجة الثلاث بايثون وجافاسكربت وVBScript الأعداد الحقيقية، وننشئها في بايثون بتخصيص عدد بعلامة عشرية فيه كما رأينا في المقال السابق للتسلسلات البسيطة؛ أما جافاسكربت وVBScript فلا يوجد تمييز واضح بين الأعداد الصحيحة والحقيقية، فما عليك إلا استخدامها وستتعامل اللغة مع ما تدخله إليها وفق المناسب.
الأعداد المركبة أو التخيلية Complex numbers
إذا كانت لديك خلفية رياضية فقد تتساءل أين الأعداد المركبة complex في هذا الشرح، والواقع أننا لا نحتاج إليها غالبًا في البرمجة، لكن على أي حال فبعض اللغات مثل بايثون توفر دعمًا مضمّنا فيها للأعداد المركبة، بينما توفر بعض اللغات الأخرى مكتبةً من الدوال التي تستطيع التعامل مع الأعداد المركبة، ونفس الأمر ينطبق على المصفوفات.
يمثَّل العدد المركب في بايثون كما يلي:
(real+imaginaryj)
وبناءً عليه تبدو عملية جمع بسيطة لعدد مركب كما يلي:
>>> M = (2+4j) >>> N = (7+6j) >>> print( M + N ) (9+10j)
تنطبق جميع عمليات الأعداد الصحيحة على الأعداد المركبة كذلك، كما توجد وحدة cmath
التي تحتوي بعض الدوال الرياضية الشائعة التي تعمل على قيم الأعداد المركبة، ولا توفِّر جافاسكربت وVBScript دعمًا للأعداد المركبة.
القيم البوليانية - True و False
سُمي هذا النوع من القيم بهذا الاسم نسبةً إلى عالم الرياضيات George Boole الذي كان يدرس المنطق في القرن التاسع عشر، ولا يحوي هذا النوع من البيانات إلا قيمتين فقط، هما True
عند التحقق أو الصحة، و false
عند عدم التحقق أو الخطأ، وتدعم بعض اللغات هذا النوع دعمًا مباشرًا، بينما تستخدم بعض اللغات الأخرى اصطلاحًا تمثل فيه قيمةً عدديةً القيمة false، وتكون تلك القيمة غالبًا هي الصفر؛ بينما تمثَّل القيمة true بالعدد (1) أو (-1)، وقد كان هذا سلوك بايثون حتى الإصدار 2.2، لكنها صارت تدعم القيم البوليانية مباشرةً بعد ذلك باستخدام القيمتين True
و False
، وهما كما ترى تبدآن بحرف كبير، فتذكر أن بايثون حساسة لحالة الأحرف.
تعرَف القيم البوليانية أحيانًا باسم قيم الحقيقة لأنها تُستخدم للتحقق مما إذا كان شيء ما صحيحًا أم لا، فإذا كتبنا برنامجًا يأخذ نسخةً احتياطيةً من جميع الملفات في مجلد ما مثلًا، فنستطيع نسخ كل ملف على حدة ثم نطلب اسم الملف التالي من النظام، وإذا لم تتبق ملفات لنسخها، فسيعيد النظام سلسلةً نصيةً فارغةً، حيث سنتحقق هنا مما إذا كان الاسم هو سلسلةً فارغةً أم لا، ونخزن النتيجة مثل قيمة بوليانية تكون قيمتها True
إذا كان الاسم سلسلةً فارغةً، و False
إذا لم يكن كذلك، وسنرى كيفية استخدام تلك النتيجة لاحقًا في هذه السلسلة.
العوامل البوليانية أو المنطقية
العامل | الوصف | الأثر |
---|---|---|
A and B | الإضافة أو AND | صحيح إذا كان كل من A و B صحيحًا أو متحققًا، وخطأ في الحالات الأخرى |
A or B | الاختيار أو OR | صحيح إذا كان أحدهما أو كلاهما صحيحًا، وخطأ إذا كان كل من A و B خاطئًا |
A == B | التساوي | صحيح إذا كان A يساوي B |
A != B | عدم التساوي | صحيح إذا كانت A لا تساوي B |
not B | النفي | صحيح إذا لم يكن B صحيحًا |
اقتباسلاحظ أن العامل الأخير يعمل على قيمة واحدة، بينما توازن بقية العوامل بين قيمتين.
تدعم VBScript القيم البوليانية كما تفعل بايثون على الصورة True
و False
، أما جافاسكربت فتدعمها لكن على الصورة true
و false
-لاحظ حالة الأحرف الصغيرة هنا-. كما ستجد أسماءً مختلفةً لنوع البيانات البولياني أو المنطقي في كل لغة، ففي بايثون ستجدها باسم bool
، أما في جافاسكربت وVBScript فاسمه Boolean
، ولا تشغل بالك بهذا لأننا لن ننشئ متغيرات من هذا النوع، لكننا سنستخدم نتائجه في الاختبارات.
الوقت والتاريخ
يُعطى التاريخ والوقت في العادة أنواعًا خاصةً بهما في البرمجة، لكن قد يمثَّلان أحيانًا في صورة عدد كبير (عدد الثواني منذ وقت أو تاريخ قديم، مثل الوقت الذي كُتب فيه نظام التشغيل)، لكن قد يكون نوع البيانات في أحيان أخرى هو ما يُعرف بالنوع المعقد الذي سنذكره في الفصل التالي، وهو يسهل استخراج الشهر واليوم والساعة…
سننظر في استخدام بايثون لوحدة time
في مقال تالٍ، أما جافاسكربت وVBScript فلديهما آليات خاصة للتعامل مع الوقت، لكننا لن ندرسها.
النوع الذي يعرفه المستخدم User Defined Type
قد لا تكفي الأنواع التي ذكرناها سابقًا لاحتياجاتنا البرمجية حتى لو دمجناها معًا، فقد نريد جمع عدة أجزاء من البيانات معًا ثم نعاملها مثل عنصر واحد، كما في وصف العنوان مثلًا، حيث يكون على هيئة "رقم المنزل والشارع والمدينة ، ثم الرمز البريدي". تسمح أغلب اللغات بجمع مثل هذه المعلومات معًا في سجل أو هيكل بيانات أو في هيئة صنف Class، وهذا الأخير في البرمجة كائنية التوجه Object Oriented.
VBScript
تبدو تعريفات السجلات في VBScript كما يلي:
Class Address Public HsNumber Public Street Public Town Public ZipCode End Class
تعني الكلمة المفتاحية Public
أن البرنامج يستطيع الوصول إلى البيانات، وعليه توجد كلمة Private
التي يمكن استخدامها لجعل البيانات خاصةً ومقصورةً على أجزاء بعينها من البرنامج، كما سنرى لاحقا.
بايثون
يختلف الأمر قليلًا في بايثون:
>>> class Address: ... def __init__(self, Hs, St, Town, Zip): ... self.HsNumber = Hs ... self.Street = St ... self.Town = Town ... self.ZipCode = Zip ...
سنترك شرح معنى كل من self
و def __init__(...)
إلى حين الحديث عن البرمجة كائنية التوجه، أما الآن فنريد ملاحظة أن هناك شرطتين سفليتين حول init
، وهذا أسلوب متبع في بايثون. لاحظ كذلك ضرورة استخدام المسافات الموضحة أعلاه، ذلك أن بايثون دقيقة في تحديد المسافات. قد يواجه البعض مشاكل أثناء كتابة ما يتشابه مع هذا المثال في محث بايثون، وستجد في نهاية هذا المقال شرحًا مختصرًا لهذه المشكلة، ثم سنشرحها بالتفصيل في جزء تالٍ من هذه السلسلة، فإذا أردت كتابة المثال أعلاه في محث بايثون؛ فتأكد من نسخ المسافات البادئة لكل سطر.
والأمر الذي نريد التوكيد عليه هنا هو أننا جمعنا عدة أجزاء من بيانات مرتبطة ببعضها بعضًا ثم وضعناها في هيكل واحد هو Address
، كما فعلنا في VBScript قبل قليل.
جافاسكربت
توفر جافاسكربت اسمًا غريبًا لهيكل بيانات العنوان في حالتنا، وهو function
، إذ ترتبط الدوال عادةً بالعمليات وليس تجميعات البيانات، غير أن دوال جافاسكربت تستطيع التعامل مع كليهما، فإذا أردنا إنشاء كائن العنوان في جافاسكربت؛ فسنكتب الآتي:
function Address(Hs,St,Town,Zip) { this.HsNum = Hs; this.Street = St; this.Town = Town; this.ZipCode = Zip; }
نريد مرةً أخرى تجاهل الصياغة واستخدام الكلمة this
هنا، والنظر إلى النتيجة التي ستكون مجموعةً من عناصر البيانات التي نستطيع القول بأنها تصف عنوانًا، ويمكننا معاملته على أنه وحدة واحدة.
والآن، كيف نصل إلى تلك البيانات بعد إنشاء هياكلها؟
الوصول إلى الأنواع التي يعرفها المستخدم
من الممكن إسناد نوع بيانات معقد إلى متغير، لكن لا يمكن الوصول إلى الحقول المنفردة دون استخدام بعض آليات الوصول الخاصة التي تحددها اللغة، وتكون نقطة .
في الغالب.
VBScript
إذا استخدمنا حالة صنف العنوان الذي عرّفناه أعلاه، فسنكتب ما يلي:
Dim Addr Set Addr = New Address Addr.HsNumber = 7 Addr.Street = "High St" Addr.Town = "Anytown" Addr.ZipCode = "123 456" MsgBox Addr.HsNumber & " " & Addr.Street & " " & Addr.Town
نحدد هنا بُعد متغير جديد هو Addr
باستخدام Dim
، ثم نستخدم الكلمتين Set
و New
لإنشاء نسخة جديدة من صنف Address
، ثم نسند القيم إلى حقول نسخة العنوان الجديدة، ثم نطبع العنوان في صندوق رسالة.
بايثون
على فرض أننا كتبنا تعريف الصنف أعلاه:
>>> Addr = Address(7,"High St","Anytown","123 456") >>> print( Addr.HsNumber, Addr.Street, Addr.Town ) 7 High St Anytown
ينشئ هذا نسخةً من نوع Address
ويسند إليه المتغير Addr
، ونستطيع تمرير قيم الحقل إلى الكائن الجديد عند إنشائه في بايثون، ثم نطبع حقول HsNumber
و Street
للنسخة المنشأة حديثًا باستخدام عامل النقطة .
.
كما يمكن إنشاء نسخ عنوان متعددة لكل منها قيمه المستقلة لأرقام البيوت والشوارع وغيرها. جرب هذا بنفسك لتتدرب عليه، فهل تستطيع معرفة كيفية استخدام هذا في مثال دفتر العناوين؟
جافاسكربت
تشبه آلية جافاسكربت هنا ما سبق ذكره لكن مع بعض التعديل، غير أن الآلية الأساسية بسيطة ومباشرة:
var addr = new Address(7, "High St", "Anytown", "123 456"); document.write(addr.HsNum + " " + addr.Street + " " + addr.Town);
إحدى الآليات التي يمكن استخدامها في جافاسكربت أيضًا هي معاملة الكائن مثل قاموس واستخدام اسم الحقل كمفتاح:
document.write( addr['HsNum'] + " " + addr['Street'] + " " + addr['Town']);
وما لم نُعط اسم الحقل في هيئة سلسلة نصية كما في حالة قراءة ملف أو إدخال مستخدم للبرنامج، فلا ننصح باستخدام هذا النموذج.
العوامل التي يعرفها المستخدم
يمكن للأنواع التي يعرِّفها المستخدم أن تكون لها عمليات معرفة لها كذلك، وذلك أساس ما يعرف بالبرمجة كائنية التوجه. الكائن هو عبارة عن تجميعة من عناصر البيانات والعمليات المرتبطة بتلك البيانات، وهي مغلفة جميعًا في وحدة واحدة، حيث تستخدم بايثون الكائنات على نطاق واسع في مكتبتها القياسية للوحدات، كما تسمح لنا كوننا مبرمجين بإنشاء أنواع الكائنات الخاصة بنا.
يحصل الوصول إلى عمليات الكائنات بنفس الطريقة التي يمكن الوصول بها إلى أعضاء البيانات لنوع معرَّف من قِبل المستخدم، أي من خلال عامل النقطة؛ أما غير هذا فتكون أشبه بالدوال، وتسمى تلك الدوال الخاصة بالتوابع methods، وقد رأيناها في حالة العملية append()
في القوائم، أينما تذكر أنه من أجل استخدامها يجب أن نربط استدعاء الدالة باسم المتغير.
>>> listObject = [] # قائمة فارغة >>> listObject.append(42) # استدعاء تابع لكائن القائمة >>> print( listObject ) [42]
يجب استيراد الوحدة عند توفير نوع كائن - يُسمى صنفًا- في وحدة بايثون كما فعلنا في sys
من قبل، ثم كتابة اسم الوحدة قبل اسم نوع الكائن عند إنشاء نسخة يمكن تخزينها في متغير مع استخدام الأقواس طبعًا، بعد ذلك نستطيع استخدام المتغير دون استخدام اسم الوحدة، ولتوضيح هذا لنَعُد إلى وحدة array
التي ذكرناها من قبل، فهي توفر الصنف array
، ولنستورد هذه الوحدة ثم ننشئ نسخةً من array
، ونسند اسم myArray
إليها، ثم نستخدم myArray
فقط للوصول إلى عملياتها وبياناتها كما يلي:
>>> import array >>> myArray = array.array('d') # array of reals(d), use module name >>> myArray.append(42) # use array operation >>> print( myArray[0]] ) # access array content 42.0 >>> print( myArray.typecode ) # access array attribute 'd'
نستورد الوحدة array
في السطر الأول إلى البرنامج، ثم نستخدم تلك الوحدة في السطر الثاني لإنشاء نسخة من صنف array
باستدعائها مثل دالة، ونحتاج هنا إلى توفير سلسلة الرموز النوعية typecode string التي توضح نوع البيانات التي يجب تخزينها. تذكر أن المصفوفات الخالصة تخزن نوعًا واحدًا من البيانات، حيث سنصل في السطر الثالث إلى إحدى عمليات صنف المصفوفة، وهي append()
التي تعامل الكائن myArray
كأنه وحدة وكأن العملية داخل الوحدة، ثم نستخدم الفهرسة لجلب البيانات التي أضفناها، نستطيع في الأخير الوصول إلى بعض البيانات الداخلية، إذ يخزن typecode
النوع الذي مررناه عند إنشاء المصفوفة، من داخل كائن myArray
صياغةً تشبه صياغة الوحدة.
لا يوجد فرق كبير بين استخدام الكائنات التي توفرها الوحدات، وبين الدوال الموجودة في الوحدات، باستثناء الحاجة إلى إنشاء نسخة instance، ويمكن النظر إلى اسم الكائن على أنه عنوان يحفظ الدوال والمتغيرات المرتبطة به مجموعةً معًا.
إحدى الطرق الأخرى التي ننظر بها للأمر هي أن الكائنات تمثل أشياء من العالم الحقيقي ونحن نستخدمها أو نفعل بها أمورًا تنفعنا، وهذا المنظور على بساطته إلا أنه الفكرة التي نشأت بسببها الكائنات في البرمجة، فنحن نكتب -برمجيًا- محاكاةً لمواقف في العالم الحقيقي.
تستطيع كل من جافاسكربت وVBScript أن تتعامل مع الكائنات، وقد كان هذا ما استخدمناه في كل أمثلة العناوين أعلاه، فقد عرفّنا صنفًا ثم أنشأنا نسخةً أسندناها إلى متغير كي نستطيع الوصول إلى خصائص تلك النسخة، ولهذا ارجع إن شئت إلى ما سبق من الشرح عن الأصناف والكائنات، وانظر كيف توفر الأصناف آليات لإنشاء أنواع جديدة من البيانات في برامجنا من خلال الربط بين بيانات النوع الجديد وعملياته معًا.
العوامل الخاصة ببايثون
إنّ الهدف من هذه السلسلة هو تعليم البرمجة للمبتدئين، ورغم أننا نستخدم بايثون في الشرح؛ إلا أنك تستطيع قراءة لغة برمجة أخرى واستخدامها بدلًا منها، بل إن هذا هو عين ما نتوقعه منك، إذ أنه لا توجد لغة برمجة بما فيها بايثون، تستطيع تنفيذ جميع المهام وحل كل المشاكل التي تواجهك برمجيًا، وبسبب ذات الهدف لن نشرح جميع الخصائص الموجودة في بايثون، بل سنركز على تلك التي يمكن إيجادها في لغات البرمجة الأخرى كذلك، ولهذا سنهمل شرح بعض الخصائص بالغة القوة في بايثون، والتي تميزها عما سواها، مثل العوامل الخاصة special operators، ذلك أن أغلب لغات البرمجة تدعم عمليات بعينها لا تدعمها لغات أخرى، وتلك العوامل الفريدة هي التي تسبب ظهور لغات برمجة جديدة، وهي من العوامل المهمة في تحديد شهرة تلك اللغات من حيث الاستخدام فيما بعد.
حيث تدعم بايثون مثلًا عمليات غير شائعة نسبيًا في لغات البرمجة الأخرى، مثل تشريح القائمة spam[X:Y]
(إلى شرائح) list slicing من أجل استخراج شريحة من وسط القائمة أو السلسلة النصية أو الصف tuple، كما تدعم إسناد الصف Tuple الذي يسمح لنا بإسناد عدة قيم متغيرات مرةً واحدةً: X, Y = (12, 34)
. كما تسهل تنفيذ العمليات على كل عضو من أعضاء تجميعة ما باستخدام الدالة map()
التي سنشرحها في مقال لاحق من هذه السلسلة، إضافةً إلى الكثير من الخصائص التي جعلت بايثون تشتهر بأنها تأتي "مع البطارية" إشارةً إلى كثرة الملحقات والمزايا التي تأتي معها. ارجع إلى توثيق بايثون للمزيد عن تلك المزايا.
تجدر أخيرًا الإشارة إلى أنه رغم قولنا بأن تلك العوامل خاصة ببايثون؛ إلا أن هذا لا يعني أنها لا توجد في لغات برمجة أخرى، بل أنها لن توجد مجتمعةً في كل لغة، فالعوامل التي نشرحها في هذه السلسلة تكون متاحةً بشكل أو بآخر في أغلب لغات البرمجة الحديثة.
يلخص هذا نظرتنا على المواد الخام للبرمجة، وسننتقل الآن إلى موضوع آخر نرى فيه كيف نستغل تلك المواد الخام في البرمجة الحقيقية.
شرح لمثال العناوين
رغم قولنا أننا سنشرح تفاصيل هذا المثال لاحقًا، إلا أننا رأينا صعوبة تنفيذ مثال بايثون من بعض القراء، ولهذا سيشرح هذا القسم شيفرة بايثون سطرًا سطرًا.
ستبدو شيفرة المثال كاملة كما يلي:
>>> class Address: ... def __init__(self, Hs, St, Town, Zip): ... self.HsNumber = Hs ... self.Street = St ... self.Town = Town ... self.Zip_Code = Zip ... >>> addr = Address(7,"High St","Anytown","123 456") >>> print( addr.HsNumber, addr.Street )
وسنشرح الآن سطرًا سطرًا:
>>> class Address:
تخبر التعليمة class
بايثون أننا على وشك تعريف نوع جديد اسمه Address
في هذه الحالة، وتشير النقطتان الرأسيتان إلى أن أي أسطر مزاحة تالية ستكون جزءًا من تعريف الصنف، وينتهي التعريف عند أول سطر غير مزاح، فإذا كنت تستخدم IDLE؛ فسترى أن المحرر قد أزاح السطر التالي تلقائيًا، أما إذا كنت تعمل من محث بايثون في سطر أوامر DOS مثلًا، فسيكون عليك إزاحة الأسطر كما هو موضح أعلاه، ولا تهتم بايثون بمقدار الإزاحة طالما أنها نفسها لكل سطر.
أما السطر الثاني:
... def __init__(self, Hs, St, Town, Zip):
يطلق على العنصر الأول في الصنف الخاص بنا "تعريف التابع method definition"، ويجب أن يكون حول الاسم شرطتان سفليتان على كل ناحية منه، وهي طريقة بايثون للأسماء التي لها أهمية خاصة، ويسمى ذلك التابع __init__
، وهو عملية خاصة تنفذها بايثون حين ننشئ نسخةً من الصنف الجديد الخاص بنا كما سنرى بعد قليل؛ أما النقطتان الرأسيتان فتخبران بايثون أن مجموعة الأسطر المزاحة التالية ستكون هي التعريف الحقيقي للتابع.
والسطر الثالث:
... self.HsNumber = Hs
يُسنِد هذا السطر -والأسطر الثلاثة التالية- قيمًا إلى الحقول الداخلية للكائن الخاص بنا، وهذه الأسطر مزاحة من تعليمة def
لتخبر بايثون أنها تشكل التعريف الحقيقي لعملية __init__
، أما السطر الفارغ، فيخبر مفسر بايثون بأن تعريف الصنف قد انتهى، لنعود مرةً أخرى إلى محث بايثون المعتاد >>>
.
>>> addr = Address(7,"High St","Anytown","123 456")
ينشئ هذا نسخةً جديدةً من النوع Address
، وتستخدم بايثون عملية __init__
المعرَّفة أعلاه لإسناد القيم التي أعطيناها إلى الحقول الداخلية، وتسنَد النسخة إلى متغير addr
كما تسنَد أي نسخة لأي نوع بيانات آخر.
>>> print( addr.HsNumber, addr.Street )
نطبع الآن قيم حقلين من الحقول الداخلية مستخدمين عامل النقطة للوصول إليهما.
خاتمة
يُعَد هذا المقال دسمًا وغنيًا بالمعلومات النظرية التي تؤسس لتعلم البرمجة على أسس سليمة، وسنعود إلى ما فيه مرات كثيرة أثناء الشرح، بما أن البيانات وأنواعها هي اللبنات التي تُصنع منها البرامج، لكن نريد التذكير هنا بأن بايثون تسمح لنا بإنشاء أنواع البيانات التي نريدها بأنفسنا ونستخدمها مثل أي نوع مضمّن فيها، وأن المتغيرات تشير إلى بيانات، وقد نحتاج إلى التصريح عنها قبل تعريفها، وهي تأتي في أنواع شتى، ويتوقف نجاح العملية التي نجريها على نوع البيانات الذي نستخدمه.
ومن أنواع البيانات البسيطة سلاسل المحارف والأعداد والقيم البوليانية أو قيم "الحقيقة"، كما تشمل أنوع البيانات المعقدة التجميعات والملفات والبيانات وأنواع البيانات المعرّفة من قِبل المستخدم.
توجد أيضًا العديد من العوامل في كل لغة برمجة، وتيُعَد تعلّم تلك العوامل جزءًا من التعود على أنواع بياناتها وعلى العمليات المتاحة لتلك الأنواع، وقد يكون العامل الواحد متاحًا لعدة أنواع، غير أن النتيجة قد لا تكون هي نفسها في كل مرة، بل ربما تختلف اختلافًا كبيرًا.
سنتابع مع المقال الموالي مع ذكر نوع أخر مهم من البيانات، وهو التجميعات Collections.
ترجمة -بتصرف- للفصل الخامس: The Raw Materials من كتاب Learning To Program لصاحبه Alan Gauld.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.