البرمجة بلغة بايثون · الفصل 2 — مفاهيم أساسية في البرمجةמושגי יסוד בתכנות · יסודות התכנות בשפת Python⌂📚🏠
الفصل 2

مفاهيم أساسية في البرمجة

מושגי יסוד בתכנות
· 30 ساعات تعليمية

في الفصل السابق كتبنا برنامجا أول. في هذا الفصل نتعلم مواد البناء التي يتكوّن منها كل برنامج: المتغيّرات التي تحفظ القيم، الأنواع التي تحدد معناها، العمليّات الحسابية التي تغيّرها، والمُدخَلات والمُخرَجات التي تصل البرنامج بالعالم.

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

2.1 كتابة خوارزمية بالكلمات – כתיבת אלגוריתם מילולי

قبل أن نكتب أمرا واحدا نسأل: ما الذي يدخل إلى البرنامج، وما الذي يجب أن يخرج منه؟ ثم نكتب الطريق بينهما بكلمات بسيطة.

عرّفنا الخوارزمية في البند 1.2 بأنها وصف مرتب ودقيق لخطوات الحل. نضيف هنا أن خطواتها منتهية، وأنها تقود من المُدخَلات إلى الحل، وأن كل خطوة فيها مفهومة ولا تترك مجالا للتخمين.

مثال 2.1
بطارية سعتها معروفة تغذي حملا تياره معروف. نريد أن نعرف كم ساعة ودقيقة تعمل قبل أن تفرغ. نكتب الخوارزمية بالكلمات.
الحل:

  1. نقرأ سعة البطارية بوحدة الأمبير ساعة.
  2. نقرأ تيار الحمل بوحدة الأمبير.
  3. نقسم السعة على التيار ونضرب الناتج في 60، فنحصل على زمن العمل بالدقائق، ونقرّبه إلى عدد صحيح.
  4. نقسم الدقائق على 60، والجزء الصحيح من الناتج هو عدد الساعات.
  5. باقي هذه القسمة هو الدقائق.
  6. نطبع الساعات والدقائق.

نلاحظ أننا لم نذكر أي أمر في بايثون. سنعود إلى هذه الخوارزمية في البند 2.15 ونترجمها إلى برنامج.

سؤال 2.1: نكتب خوارزمية بالكلمات لتحويل مدة بالدقائق إلى ساعات ودقائق.

2.2 المتغيّر – משתנה

المتغيّر (משתנה): اسم نعطيه لقيمة محفوظة في ذاكرة الحاسوب. نتخيله صندوقا عليه اسم، وفي داخله قيمة واحدة في كل لحظة.
volts = 12
current = 0.5
print(volts)
print(current)
المُخرَج
12
0.5
volts = 12volts12volts = 9volts9
القيمة الجديدة تحل مكان القديمة: في الصندوق قيمة واحدة فقط

نختار للمتغيّر اسما يدل على معناه: current أوضح من c. وللأسماء قواعد:

خطأ شائع: اسم يبدأ برقم يوقف البرنامج قبل أن يبدأ، واختلاف حرف واحد يعني متغيّرا آخر لم نعرّفه:
2volts = 12
المُخرَج
SyntaxError: invalid decimal literal
Volts = 12
print(volts)
المُخرَج
NameError: name 'volts' is not defined
ملاحظة: الكلمة print ليست محجوزة بالمعنى الدقيق، لكنها اسم دالة جاهزة، وإذا استعملنا هذا الاسم لمتغيّر فقدنا الدالة. لذلك نتجنبه.

2.3 الفئة، الصفات والعمليّات – מחלקה, תכונות ופעולות

نفكر في مقاومة على طاولة المختبر. كل المقاومات من النوع نفسه، لكن لكل واحدة قيمتها وقدرتها. الفئة هي الوصف العام، والكائن هو قطعة محددة صُنعت حسب هذا الوصف.

المصطلحبالعبريةالمعنىمثال من المختبر
الفئةמחלקהوصف عام لنوع من الأشياءالمقاومة بشكل عام
الكائنעצםنسخة محددة من الفئةهذه المقاومة التي في يدي
الصفةתכונהقيمة يحملها الكائنالقيمة بالأوم
العمليّةפעולהعمل ينفذه الكائن أو يُنفَّذ عليهحساب هبوط الجهد على المقاومة

في بايثون كل قيمة هي كائن من فئة ما. نصل إلى صفة أو إلى عمليّة بواسطة نقطة بعد اسم الكائن. العمليّة تأتي بعدها أقواس، والصفة بلا أقواس:

label = "solar panel"
print(label.upper())
print(label.count("a"))
reading = 12.0
print(reading.is_integer())
print(reading.real)
المُخرَج
SOLAR PANEL
2
True
12.0

هكذا عملنا في الفصل الأول مع الفئة الجاهزة Turtle: أنشأنا كائنا، وأعطيناه أوامر. أما كتابة فئات جديدة بأنفسنا فنتعلمها في الفصل 8.

import turtle
pen = turtle.Turtle()
pen.forward(100)
print(pen.position())

2.4 أنواع المعطيات الأساسية – טיפוסי נתונים בסיסיים

نوع القيمة يحدد ماذا يمكن أن نفعل بها: الأعداد نجمعها، والجمل النصية نصلها ببعضها. نوع المعطيات (טיפוס נתונים) هو الفئة التي تنتمي إليها القيمة.

النوعبالعبريةمعناهأمثلة
intשלםعدد صحيح250 , -3 , 0
floatעשרוניعدد عشري11.7 , 0.02 , 3.0
strמחרוזתجملة نصية بين علامتي اقتباس"fan" , "12"
boolבוליאניصواب أو خطأTrue , False
samples = 250
volts = 11.7
device = "fan"
running = True
print(type(samples))
print(type(volts))
print(type(device))
print(type(running))
المُخرَج
<class 'int'>
<class 'float'>
<class 'str'>
<class 'bool'>

العدد 3.0 من النوع float مع أن قيمته صحيحة، لأن فيه نقطة. والجملة النصية "12" من النوع str مع أن أحرفها أرقام، لأنها بين علامتي اقتباس.

2.5 مجالات القيم وحجمها في الذاكرة – תחומי הערכים וגודלם בזיכרון

الوحدة الجاهزة sys تتيح لنا أن نسأل بايثون عن نفسها. نكتب import sys في بداية البرنامج، ثم نقرأ صفاتها:

import sys
print(2 ** 100)
print(sys.float_info.max)
print(sys.float_info.min)
print(sys.float_info.dig)
print(sys.int_info.bits_per_digit)
print(sys.float_info.max * 10)
المُخرَج
1267650600228229401496703205376
1.7976931348623157e+308
2.2250738585072014e-308
15
30
inf

والدالة sys.getsizeof تعطي عدد البايتات التي تشغلها القيمة في الذاكرة:

import sys
print(sys.getsizeof(5))
print(sys.getsizeof(2 ** 100))
print(sys.getsizeof(1.5))
print(sys.getsizeof("abc"))
print(sys.getsizeof(True))
المُخرَج
28
40
24
44
28
ملاحظة: هذه الأرقام من الحاسوب الذي بُني عليه الكتاب، وقد تختلف في حاسوب آخر. المهم هو الفكرة: حتى العدد الصغير كائن كامل، ولذلك يشغل بايتات أكثر مما يكفي لتخزين قيمته في متحكّم صغير، والعدد الكبير يشغل أكثر من الصغير.

2.6 أوامر الإسناد – פקודות השמה

في أمر الإسناد (השמה) أولا تُحسب القيمة التي على يمين الإشارة =، وبعدها توضع في المتغيّر الذي على يسارها. لذلك count = count + 1 ليست معادلة، بل تعني: نأخذ القيمة الحالية، نضيف إليها واحدا، ونضع النتيجة مكانها.

count = 10
count = count + 1
count += 4
count -= 2
count *= 3
print(count)
المُخرَج
39
الأمرعمله
count += 4مثل count = count + 4
count -= 2مثل count = count - 2
count *= 3مثل count = count * 3
count /= 2مثل count = count / 2
خطأ شائع: الجهة اليسرى من الإسناد يجب أن تكون اسم متغيّر:
12 = volts
المُخرَج
SyntaxError: cannot assign to literal here. Maybe you meant '==' instead of '='?

يمكن الإسناد إلى أكثر من متغيّر في أمر واحد:

v, i = 12, 0.5
print(v, i)
a = b = 0
print(a, b)
المُخرَج
12 0.5
0 0
مثال 2.2
نبدّل بين قيمتي متغيّرين. إذا كتبنا a = b ثم b = a ضاعت قيمة a الأصلية، ولذلك نحفظها أولا في متغيّر مساعد.
الحل:
a = 3
b = 8
temp = a
a = b
b = temp
print(a, b)
المُخرَج
8 3
temp = aa3temp3b8a = ba8temp3b8b = tempa8temp3b3
التبديل بمتغيّر مساعد: الخانة الملوّنة هي التي تغيّرت في كل خطوة

وفي بايثون طريقة أقصر، إذ تُحسب الجهة اليمنى كلها قبل الإسناد:

a = 3
b = 8
a, b = b, a
print(a, b)
المُخرَج
8 3

2.7 تعريف المتغيّرات وتهيئتها – הגדרה ואתחול של משתנים

المتغيّر يولد في أول مرة نسند إليه قيمة، وهذه هي تهيئته (אתחול). لا نكتب نوعه مسبقا، فبايثون تعرفه من القيمة. وقبل الإسناد الأول لا وجود له:

print(power)
power = 60
المُخرَج
NameError: name 'power' is not defined

الترتيب هنا هو الخطأ: البرنامج يُنفَّذ من الأعلى إلى الأسفل، ولا ينظر إلى ما سيأتي. والدالة type تكشف نوع المتغيّر في كل لحظة، وقد يتغيّر مع القيمة:

x = 5
print(type(x))
x = 2.5
print(type(x))
x = "off"
print(type(x))
المُخرَج
<class 'int'>
<class 'float'>
<class 'str'>
ملاحظة: السماح بتغيير النوع لا يعني أنه أسلوب جيد. متغيّر يبدأ عددا وينتهي جملة نصية يربك من يقرأ البرنامج، ولذلك يبقى كل متغيّر عندنا على نوع واحد.

2.8 المعاملات الحسابية – אופרטורים חשבוניים

الأمرعمله
a + bالجمع
a - bالطرح
a * bالضرب
a / bالقسمة، ونتيجتها عدد عشري دائما
a ** bالرفع إلى قوة
print(7 + 2)
print(7 - 2)
print(7 * 2)
print(7 / 2)
print(8 / 2)
print(2 ** 10)
المُخرَج
9
5
14
3.5
4.0
1024
تنبيه: القسمة / تعطي float حتى عندما تكون النتيجة عددا صحيحا: 8 / 2 يعطي 4.0. وفي لغات أخرى يختلف هذا، فلا نحمل معنا عادات منها.
مثال 2.3
حمل يعمل بجهد 12 V وتيار 1.5 A مدة أربع ساعات. نحسب قدرته والطاقة التي يستهلكها.
الحل:
P = V · I
E = P · t
volts = 12
current = 1.5
power = volts * current
hours = 4
energy = power * hours
print(power)
print(energy)
المُخرَج
18.0
72.0

العدد الصحيح مضروبا في عدد عشري يعطي عددا عشريا، ولذلك ظهرت النتيجتان بنقطة.

سؤال 2.2: ماذا يطبع البرنامج التالي؟
a = 9
b = 4
print(a / b)
print(a * b - 1)
print(a ** 2)

2.9 خارج القسمة وباقي القسمة – אופרטור מנה ושארית חלוקה

المعامل // يعطي خارج القسمة (מנה) بعد حذف الكسر، والمعامل % يعطي الباقي (שארית). هذان المعاملان يظهران في كل امتحان تقريبا. وإذا كان أحد العددين عشريا جاءت النتيجة عشرية أيضا، كما في السطرين الأخيرين من مُخرَج البرنامج التالي.

print(17 / 5)
print(17 // 5)
print(17 % 5)
print(17.5 // 5)
print(17.5 % 5)
المُخرَج
3.4
3
2
3.0
2.5
مثال 2.4
محطة تعمل منذ 7384 ثانية. نحوّل هذه المدة إلى ساعات ودقائق وثوان.
الحل:

في الساعة 3600 ثانية. خارج القسمة هو الساعات، والباقي هو الثواني التي لم تكمل ساعة. نكرر الأمر نفسه مع الدقائق:

seconds = 7384
hours = seconds // 3600
left = seconds % 3600
minutes = left // 60
secs = left % 60
print(hours, minutes, secs)
المُخرَج
2 3 4
مثال 2.5
نرسل 1000 بايت في رزم، في كل رزمة 64 بايتا. كم رزمة كاملة نرسل، وكم بايتا يبقى لرزمة أخيرة؟
الحل:
data = 1000
size = 64
full = data // size
rest = data % size
print(full, rest)
المُخرَج
15 40
تنبيه: مع الأعداد السالبة يُقرَّب خارج القسمة نحو الأسفل، لا نحو الصفر. لذلك -7 // 2 يعطي -4 وليس -3، والباقي 1 موجب، لأن −4 · 2 + 1 = −7. أما الدالة int في السطر الثالث، وسنتعلمها في البند 2.12، فتحذف الكسر نحو الصفر، ولذلك تعطي -3:
print(-7 // 2)
print(-7 % 2)
print(int(-7 / 2))
المُخرَج
-4
1
-3
تدريب سريع — خارج القسمة والباقي
123 // 4
223 % 4
38 // 9
48 % 9
540 % 8
62.5 // 1
الإجابات: 1 5 2 3 3 0 4 8 5 0 6 2.0

2.10 دوال رياضية جاهزة – פעולות מתמטיות בסיסיות

الأمرعمله
pow(a, b)الرفع إلى قوة، مثل a ** b
max(a, b, ...)أكبر القيم
min(a, b, ...)أصغر القيم
abs(x)القيمة المطلقة
round(x, n)التقريب إلى n خانات بعد النقطة؛ بدون n إلى عدد صحيح
sum([a, b, ...])مجموع قائمة قيم
divmod(a, b)خارج القسمة والباقي معا
print(pow(2, 8))
print(max(4.1, 3.9, 5.0))
print(min(4.1, 3.9, 5.0))
print(abs(-12.5))
print(round(3.14159, 2))
print(round(3.7))
print(sum([12, 11.5, 12.5]))
print(divmod(17, 5))
المُخرَج
256
5.0
3.9
12.5
3.14
4
36.0
(3, 2)

الأقواس المربعة في sum تكوّن قائمة قيم، وسنتعرف إليها في الفصل 6. والأقواس المستديرة في نتيجة divmod تجمع قيمتين معا.

تنبيه: التقريب round لا يتصرف كما تعلمنا في المدرسة: العدد الواقع في منتصف الطريق بالضبط يُقرَّب إلى العدد الزوجي الأقرب. والمثال الثالث يبدو خطأ لأن 2.675 مخزَّن في الحاسوب أقل بقليل من قيمته:
print(round(2.5))
print(round(3.5))
print(round(2.675, 2))
المُخرَج
2
4
2.67
مثال 2.6
ثلاث قراءات لجهد بطارية. نحسب الفرق بين أعلى قراءة وأدناها، ومتوسط القراءات.
الحل:
a = 11.8
b = 12.4
c = 12.0
high = max(a, b, c)
low = min(a, b, c)
print(round(high - low, 2))
print(round(sum([a, b, c]) / 3, 2))
المُخرَج
0.6
12.07

الوحدة random تعطي قيما عشوائية، وهي مفيدة لمحاكاة حسّاس قبل أن يكون بين أيدينا. الدالة randint تعطي عددا صحيحا في المجال شاملا طرفيه، وrandom() تعطي عددا عشريا بين 0 و1، وuniform عددا عشريا في المجال:

import random
random.seed(7)
print(random.randint(1, 6))
print(random.randint(1, 6))
print(round(random.random(), 3))
print(round(random.uniform(11.5, 12.5), 2))
المُخرَج
3
2
0.395
11.55
ملاحظة: الأمر random.seed(7) يثبّت نقطة البداية، فنحصل في كل تشغيل على القيم نفسها. وضعناه هنا كي يطابق المُخرَج ما في الكتاب؛ من دونه تتغيّر القيم في كل تشغيل.

2.11 التعابير الحسابية وترتيب العمليّات – ביטויים חשבוניים וסדר קדימויות

الترتيبالعمليّاتملاحظة
1( )الأقواس أولا
2**من اليمين إلى اليسار
3-xالإشارة السالبة، بعد القوة
4* / // %من اليسار إلى اليمين
5+ -من اليسار إلى اليمين
print(2 + 3 * 4)
print((2 + 3) * 4)
print(2 ** 3 ** 2)
print(-2 ** 2)
print(20 / 2 * 5)
المُخرَج
14
20
512
-4
50.0
خطأ شائع: ننسى الأقواس عندما نحسب متوسطا، فيعمل البرنامج ويعطي نتيجة خاطئة بلا أي رسالة:
a = 10
b = 20
print(a + b / 2)
print((a + b) / 2)
المُخرَج
20.0
15.0
مثال 2.7
نحسب المقاومة المكافئة لمقاومتين متوازيتين، 100 Ω و300 Ω.
الحل:
R = R1 · R2 R1 + R2

خط الكسر يجمع المقام كله، أما في الشيفرة فلا يوجد خط، ولذلك نكتب الأقواس بأنفسنا:

r1 = 100
r2 = 300
total = r1 * r2 / (r1 + r2)
print(total)
المُخرَج
75.0
تدريب سريع — ترتيب العمليّات
11 + 2 * 3
2(1 + 2) * 3
310 - 4 - 3
42 * 3 ** 2
518 / 3 / 2
67 % 4 * 2
الإجابات: 1 7 2 9 3 3 4 18 5 3.0 6 6
▶تجربة حية — مختبر المتغيّرات والعمليّاتنشغّل البرامج خطوة بعد خطوة ونرى قيمة كل متغيّر تتغيّر أمامنا. لا يوجد في المختبر إدخال من المستخدم ولا import، ولذلك نكتب القيم مباشرة في المتغيّرات.
⚠
المختبر غير متاح الآن. المادة في هذا الفصل كاملة من دونه — نواصل القراءة، ونعود إلى التجربة لاحقا أو نفتحها مباشرة من الرابط الذي تحت الإطار.
https://fahed-lab.com/electronics/python_basics#basics
نفتح المختبر في صفحة مستقلة ↗ fahed-lab.com/electronics/python_basics#basics

2.12 التحويل بين الأنواع – המרות בין טיפוסי הנתונים

الدوال int وfloat وstr وbool تحوّل قيمة إلى النوع الذي تحمل اسمه:

print(int(3.9))
print(int(-3.9))
print(int("42"))
print(float(7))
print(float("3.5"))
print(str(12.5))
print(bool(0))
print(bool(0.5))
print(bool(""))
print(bool("0"))
print(int(True))
المُخرَج
3
-3
42
7.0
3.5
12.5
False
True
False
True
1

التحويل قد يفشل. جملة نصية فيها نقطة لا تتحوّل مباشرة إلى int، ولا نستطيع أن نصل عددا بجملة نصية من دون تحويل:

print(int("3.5"))
المُخرَج
ValueError: invalid literal for int() with base 10: '3.5'
print("Volts: " + 12)
المُخرَج
TypeError: can only concatenate str (not "int") to str

الإشارة + تعني الجمع بين عددين والوصل بين جملتين نصيتين، والإشارة * تعني الضرب بين عددين وتكرار جملة نصية:

print("Volts: " + str(12))
print("12" + "3")
print(12 + 3)
print("ab" * 3)
المُخرَج
Volts: 12
123
15
ababab

2.13 عرض القيم بطرق مختلفة – הצגת ערכים בצורות שונות

العدد نفسه يمكن كتابته بأكثر من نظام عد، كما تعلمنا في موضوع الأنظمة الرقمية. والحاسوب يخزّن كل حرف كعدد.

الأمرعمله
bin(x)يعرض العدد بالنظام الثنائي، كجملة نصية تبدأ بـ 0b
hex(x)يعرض العدد بالنظام السادس عشر، كجملة نصية تبدأ بـ 0x
0b1101 , 0xFFكتابة عدد مباشرة بالنظامين
int("1101", 2)تحويل جملة نصية من نظام عد إلى عدد
ord("V")رقم الحرف في جدول الترميز
chr(86)الحرف الذي يحمل هذا الرقم
print(bin(13))
print(hex(255))
print(0b1101)
print(0xFF)
print(int("1101", 2))
print(int("FF", 16))
print(ord("V"))
print(chr(86))
print(bin(ord("V")))
print(hex(ord("V")))
المُخرَج
0b1101
0xff
13
255
13
255
86
V
0b1010110
0x56

الأسطر الثلاثة الأخيرة تُظهر ما يحدث حقا عندما نرسل حرفا مثل V إلى أردوينو، كما سنفعل في الفصل 10: لا يُرسل حرف، بل بايت قيمته 0x56.

سؤال 2.3: (أ) ماذا يعطي hex(16)؟
(ب) ماذا يعطي bin(5)؟
(ج) ماذا يعطي chr(ord("A"))؟

2.14 أنواع الأخطاء – שגיאות לוגיות, שגיאות תחביר, שגיאות בזמן ריצה

النوعبالعبريةمتى يظهركيف نكتشفه
خطأ نحويשגיאת תחבירقبل التشغيلرسالة خطأ، ولا يُنفَّذ أي أمر
خطأ تشغيلשגיאה בזמן ריצהأثناء التشغيلرسالة خطأ بعد أن عملت الأسطر السابقة
خطأ منطقيשגיאה לוגיתلا يظهر وحدهلا رسالة: النتيجة خاطئة، ونكتشفها بالفحص

الخطأ النحوي: قوس ناقص، فلا يطبع البرنامج شيئا، حتى ما كُتب قبل الخطأ:

print("start")
print("end"
المُخرَج
SyntaxError: '(' was never closed

خطأ التشغيل: الأمر الأول يعمل، ثم يتوقف البرنامج عند القسمة على صفر أو عند اسم غير معروف، ولا يصل إلى ما بعده:

print("start")
r = 0
print(12 / r)
print("end")
المُخرَج
start
ZeroDivisionError: division by zero
print("start")
print(volt)
المُخرَج
start
NameError: name 'volt' is not defined

الخطأ المنطقي هو الأخطر: البرنامج التالي يعمل بلا شكوى، لكنه يضرب بدل أن يقسم في قانون أوم. التيار الصحيح هو 3 A:

volts = 12
resistance = 4
current = volts * resistance
print(current)
المُخرَج
48
ملاحظة: نجرب البرنامج دائما على مثال نعرف نتيجته. هذه هي الطريقة الوحيدة لكشف الخطأ المنطقي. ونقرأ رسالة الخطأ من آخرها: السطر الأخير يقول ما حدث.

2.15 الإدخال والإخراج ووصل الجمل النصية – פעולות קלט/פלט ושרשור מחרוזות

الدالة print تطبع قيما، وتفصل بينها بمسافة، وتنتقل إلى سطر جديد. الوسيط sep يغيّر الفاصل، والوسيط end يغيّر ما يأتي في النهاية. أما وصل الجمل النصية (שרשור) بالإشارة + فلا يضيف مسافة، ويحتاج إلى تحويل الأعداد:

volts = 12
print("Volts:", volts)
print("a", "b", "c", sep="-")
print("no new line", end=" | ")
print("same line")
print()
print("Volts: " + str(volts))
المُخرَج
Volts: 12
a-b-c
no new line | same line

Volts: 12

الدالة input تعرض رسالة، تنتظر ما يكتبه المستخدم، وتعيده جملة نصية دائما:

name = input("Sensor name: ")
print("Reading", name)
المُخرَج
Sensor name: Temp-1
Reading Temp-1
خطأ شائع: ما يعود من input هو جملة نصية حتى لو كتب المستخدم عددا. لذلك تصل الإشارة + الجملتين النصيتين بدل أن تجمعهما:
a = input("a: ")
b = input("b: ")
print(a + b)
print(int(a) + int(b))
المُخرَج
a: 12
b: 30
1230
42

لذلك نحوّل مباشرة عند القراءة: int(input()) أو float(input()). نعود الآن إلى خوارزمية البطارية من البند 2.1، وكل خطوة منها تصبح أمرا:

مثال 2.8
نكتب برنامج زمن عمل البطارية.
الحل:
capacity = float(input("Capacity (Ah): "))
load = float(input("Load (A): "))
total = round(capacity / load * 60)
hours = total // 60
minutes = total % 60
print("Runs for", hours, "h", minutes, "min")
المُخرَج
Capacity (Ah): 20
Load (A): 3
Runs for 6 h 40 min

2.16 جدول المتابعة – ביצוע טבלת מעקב

جدول المتابعة (טבלת מעקב) يعرض ما يحدث في البرنامج أمرا بعد أمر: عمود لكل متغيّر وعمود للمُخرَج. الخانة الفارغة تعني أن القيمة لم تتغير. وفي الفصل التالي يُضاف عمود لكل شرط.

مثال 2.9
نتابع البرنامج التالي. نلاحظ أن القدرة حُسبت قبل أن يتغيّر الجهد، ولا تتغيّر معه.
الحل:
volts = 12
current = 2
power = volts * current
volts = volts - 1
print(volts, power)
متابعة البرنامج
الأمرvoltscurrentpowerالمُخرَج
volts = 1212
current = 22
power = volts * current24
volts = volts - 111
print(volts, power)11 24
مثال 2.10
نحوّل ثواني إلى دقائق وثوان. نستعمل هنا المتغيّر seconds مرتين، فننتبه إلى أن الترتيب مهم: لو غيّرنا قيمته قبل حساب الدقائق لفسد الحساب.
الحل:
seconds = int(input("Seconds: "))
minutes = seconds // 60
seconds = seconds % 60
print(minutes, seconds)
متابعة البرنامج للمُدخَل 130
الأمرsecondsminutesالمُخرَج
seconds = int(input("Seconds: "))130Seconds: 130
minutes = seconds // 602
seconds = seconds % 6010
print(minutes, seconds)2 10
سؤال 2.4: نبني جدول متابعة للبرنامج التالي ونكتب المُخرَج.
x = 7
y = x % 3
x = x // 2 + y
y = y * x
print(x, y)
مشروع الكتاب: محطة القياس · المرحلة 2 — المحطة تقرأ

في الفصل السابق رسمنا محطة القياس التي تعمل ببطارية ولوح شمسي. الآن تبدأ المحطة بالقراءة: المحوّل التماثلي-الرقمي ذو العشر خانات يعطي عددا من 0 حتى 1023 يمثل جهدا من 0 حتى 5 V. جهد البطارية يدخله عبر مقسّم جهد يقسم على 4. وحسّاس الحرارة يعطي 10 mV لكل درجة، أي 0.01 V.

adc_batt = int(input("ADC battery: "))
adc_temp = int(input("ADC temp: "))
step = 5 / 1023
battery = adc_batt * step * 4
temp = adc_temp * step * 100
print("Battery:", round(battery, 2), "V")
print("Temp:", round(temp, 1), "C")
المُخرَج
ADC battery: 620
ADC temp: 82
Battery: 12.12 V
Temp: 40.1 C

نجرّب بأنفسنا: ما قراءة المحوّل الأقرب إلى 12 V للبطارية؟ ونفحص الجواب في البرنامج.

أهمّ أفكار الفصل:

ملخّص أوامر الفصل:

الأمرعمله
x = 5 x += 1الإسناد
+ - * / ** // %المعاملات الحسابية
type(x)نوع القيمة
int(x) float(x) str(x) bool(x)التحويل بين الأنواع
pow max min abs round sum divmodدوال رياضية جاهزة
import random import sysوحدات جاهزة
bin(x) hex(x) ord(c) chr(n)طرق عرض القيم
print(a, b, sep="", end="")الإخراج
float(input("..."))قراءة عدد من المستخدم

قاموس المصطلحات – מילון מונחים:

بالعربيةبالعبرية (كما تظهر في الامتحان)English
الخوارزميةאלגוריתםAlgorithm
المتغيّرמשתנהVariable
الإسنادהשמהAssignment
التهيئةאתחולInitialization
نوع المعطياتטיפוס נתוניםData type
عدد صحيح · عدد عشريשלם · עשרוניInteger · Float
جملة نصيةמחרוזתString
الفئة · الكائنמחלקה · עצםClass · Object
الصفة · العمليّةתכונה · פעולהAttribute · Method
خارج القسمة · الباقيמנה · שאריתQuotient · Remainder
الخطأ النحويשגיאת תחבירSyntax error
خطأ التشغيلשגיאה בזמן ריצהRuntime error
الخطأ المنطقيשגיאה לוגיתLogical error
الوصلשרשורConcatenation
جدول المتابعةטבלת מעקבTrace table
الإجابات النهائية لأسئلة الفصل
2.1 نقرأ المدة، نقسمها على 60 ونأخذ الجزء الصحيح فنحصل على الساعات، وباقي القسمة هو الدقائق، ثم نطبعهما.
2.2 2.25 , 35 , 81
2.3 (أ) 0x10 ، (ب) 0b101 ، (ج) A
2.4 4 4

أسئلة للتمرين:

المستوى الأول — أساسي
1.
ماذا يطبع البرنامج؟
a = 14
b = 4
print(a // b, a % b)
print(a / b)
print(a ** 2 - b)
print(type(a / 2))
الإجابات: 3 2 , 3.5 , 192 , <class 'float'>
2.
ما نوع كل قيمة؟ القيمة الأخيرة مقارنة، ونتيجتها صواب أو خطأ، وسنتعلم المقارنات في الفصل 3.
(أ) 7 / 7
(ب) 7 // 7
(ج) "7"
(د) 7 > 7
الإجابات: (أ) float ، (ب) int ، (ج) str ، (د) bool
3.
نكتب برنامجا يقرأ جهدا ويطبع نصفه.
الإجابات:
volts = float(input("V: "))
print("Half:", volts / 2)
4.
نصلح الخطأين في هذا البرنامج. المطلوب طباعة مجموع عددين يكتبهما المستخدم.
a = input("a: ")
b = input("b: ")
print("Sum: " + a + b)
الإجابات:
a = int(input("a: "))
b = int(input("b: "))
print("Sum: " + str(a + b))
المستوى الثاني — متوسط
5.
شحنة البطارية هي حاصل ضرب التيار في الزمن. نكتب برنامجا يقرأهما ويطبع الشحنة.
الإجابات:
amps = float(input("Current (A): "))
hours = float(input("Hours: "))
print("Charge:", amps * hours, "Ah")
للقيمتين 2.5 و4 يطبع: Charge: 10.0 Ah
6.
حسّاس يعطي الحرارة بالفهرنهايت. نكتب برنامجا يحوّلها إلى درجات مئوية، مقرّبة إلى خانة واحدة.
C = (F − 32) · 5 9
الإجابات:
f = float(input("Fahrenheit: "))
c = (f - 32) * 5 / 9
print(round(c, 1))
للمُدخَل 98.6 يطبع: 37.0
7.
نكتب برنامجا لمقسّم جهد: يقرأ جهد الدخل والمقاومتين ويطبع جهد الخرج.
الإجابات:
Vout = Vin · R2 R1 + R2
vin = float(input("Vin: "))
r1 = float(input("R1: "))
r2 = float(input("R2: "))
vout = vin * r2 / (r1 + r2)
print("Vout:", round(vout, 2))
للقيم 12, 1000, 500 يطبع: Vout: 4.0
8.
في المخزن قطع إلكترونية تُلفّ في بكرات. نكتب برنامجا يقرأ عدد القطع وعدد القطع في البكرة، ويطبع عدد البكرات الكاملة وما يبقى.
الإجابات:
parts = int(input("Parts: "))
reel = int(input("Parts per reel: "))
print("Full reels:", parts // reel)
print("Left over:", parts % reel)
للقيمتين 1250 و300 يطبع: Full reels: 4 , Left over: 50
9.
نبني جدول متابعة لبرنامج تحويل الثواني من البند 2.16 للمُدخَل 3599.
الإجابات:
الأمرsecondsminutesالمُخرَج
seconds = int(input("Seconds: "))3599Seconds: 3599
minutes = seconds // 6059
seconds = seconds % 6059
print(minutes, seconds)59 59
المستوى الثالث — تحدٍّ
10.
نكتب برنامجا يقرأ عددا بين 0 و255، ويطبعه بالنظامين الثنائي والسادس عشر، ثم يطبع خارج قسمته وباقي قسمته على 16. ما علاقة النتيجتين بالخانتين في النظام السادس عشر؟
الإجابات:
value = int(input("Value: "))
print(bin(value))
print(hex(value))
print(value // 16, value % 16)
للمُدخَل 202 يطبع: 0b11001010 , 0xca , 12 10. خارج القسمة والباقي هما الخانتان نفسهما: c وa تساويان 12 و10.
11.
نكتب برنامجا يقرأ قراءة محوّل بعشر خانات ويطبع النسبة المئوية من المجال كله، مقرّبة إلى خانة واحدة.
الإجابات:
adc = int(input("ADC: "))
percent = adc * 100 / 1023
print(round(percent, 1), "%")
للمُدخَل 512 يطبع: 50.0 %
12.
نحاكي حسّاسا: قراءته 20 درجة مع ضجيج عشوائي مقداره نصف درجة على الأكثر في كل اتجاه. نكتب برنامجا يطبع قراءة واحدة مقرّبة إلى خانتين.
الإجابات:
import random
random.seed(3)
reading = 20 + random.uniform(-0.5, 0.5)
print(round(reading, 2))
مع هذه النقطة الابتدائية يطبع: 19.74
13.
نكتب برنامجا يقرأ عدد خانات ثنائية، ويطبع عدد البايتات الكاملة، الخانات الزائدة، وعدد البايتات اللازمة لتخزينها كلها، من دون أمر شرطي.
الإجابات:
bits = int(input("Bits: "))
print("Bytes:", bits // 8)
print("Extra bits:", bits % 8)
print("Bytes needed:", (bits + 7) // 8)
للمُدخَل 20 يطبع: Bytes: 2 , Extra bits: 4 , Bytes needed: 3

שאלות בגרות – أسئلة بجروت للفصل 2

السؤال التالي كله يحتاج إلى حلقات وقوائم وعمليّات من الفصول القادمة. لكن جوهره، ولا سيما البند (ج)، هو استخراج خانات عدد بالمعاملين // و%، وهذا نستطيع أن نفعله منذ الآن. يظهر السؤال بالعبرية كما في الامتحان.
بجروت 2026 السؤال 9 — خانات عدد من ثلاث خانات
بجروت 2026
البندالمطلوبالإجابة
(ج)مجموع خانات عدد موجب من ثلاث خانات.في الأسفل
(أ) ، (ب)يعتمدان على الحلقات والقوائم والعمليّات.في الفصل 7
الحل الكامل بالعربية: fahed-lab.com/exams/electronics-815381/815381/solutions/solution-2026

لم نتعلم كتابة العمليّات بعد، ولذلك نحسب مباشرة لعدد واحد. num // 100 يعطي خانة المئات، وnum % 10 يعطي خانة الآحاد، و(num // 10) % 10 يعطي خانة العشرات:

num = 472
hundreds = num // 100
tens = (num // 10) % 10
ones = num % 10
print(hundreds, tens, ones)
print(hundreds + tens + ones)
المُخرَج
4 7 2
13