الفصل الخامس: التحكم في سير البرنامج – الشروط والتكرار
مقدمة الفصل
تخيل أنك تتبع وصفة طعام. بعض الخطوات تقول: “إذا كنت تريدها حارة، أضف الفلفل”. وخطوات أخرى تقول: “كرر الخلط لمدة دقيقتين”. حتى الآن، كانت برامجنا مثل وصفة بدون هذه الخيارات؛ تنفذ الأوامر سطرًا تلو الآخر بالترتيب.
القوة الحقيقية للبرمجة تكمن في جعل البرنامج يتصرف مثل طاهٍ ذكي، قادر على اتخاذ القرارات وتكرار المهام بكفاءة. في هذا الفصل، ستتعلم كيف تمنح برامجك هذه القدرة باستخدام أداتين أساسيتين:
- الشروط (Conditional Statements): لجعل البرنامج يختار مسارًا على حساب مسار آخر.
- الحلقات (Loops): لتنفيذ نفس المهمة عدة مرات دون الحاجة لكتابة الكود مرارًا وتكرارًا.
1. الشروط: تعليم البرنامج كيفية اتخاذ القرارات
تمامًا كما تتخذ قرارات في حياتك اليومية، يمكن لبرنامجك اتخاذ قرارات. المبدأ بسيط: أنت تطرح سؤالاً على البرنامج، وإذا كانت الإجابة “نعم” (أو True
)، فإنه يقوم بمهمة معينة.
أ. بنية if
الأساسية: الخطة أ
تُستخدم جملة if
لطرح سؤال. إذا كانت نتيجة السؤال True
، يتم تنفيذ كتلة الكود التي تليها.
البنية الأساسية:
if [سؤال أو شرط نتيجته True]:
# افعل هذا الأمر
# وافعل هذا الأمر أيضًا
age = 20
# السؤال: هل قيمة المتغير age أكبر من أو تساوي 18؟
if age >= 18:
# هذه الكتلة لن تنفذ إلا إذا كانت الإجابة "نعم"
print("أنت مؤهل للتصويت.")
print("الرجاء التأكد من تسجيل اسمك.")
قاعدة ذهبية في بايثون: المسافات البادئة (Indentation)
لاحظ أن الأسطر التابعة لـ if
تبدأ بمسافة بادئة (عادة 4 مسافات). هذه المسافة تخبر بايثون أن هذه الأوامر “تنتمي” إلى جملة if
. إنها ليست اختيارية للتنسيق، بل هي جزء أساسي من بنية اللغة. بدونها، لن يعرف البرنامج ما الذي يجب تنفيذه عند تحقق الشرط، وسيعطيك خطأ IndentationError
.
ب. إضافة else
: الخطة ب
المشكلة: ماذا لو لم يكن شرط if
صحيحًا؟ في مثالنا السابق، إذا كان العمر 15، فلن يتم طباعة أي شيء.
الحل: نستخدم else
لتحديد “خطة بديلة” أو ما يجب فعله إذا كانت نتيجة سؤال if
هي False
.
temperature = 15
# السؤال: هل الحرارة أكبر من 25؟
if temperature > 25:
# الخطة أ: إذا كانت الإجابة "نعم"
print("إنه يوم حار!")
else:
# الخطة ب: في جميع الحالات الأخرى
print("الطقس معتدل.")
else
لا تحتاج إلى شرط خاص بها؛ إنها ببساطة تلتقط كل الحالات التي لم يغطها شرط if
.
ج. الشروط المتعددة مع elif
المشكلة: ماذا لو كان لديك أكثر من احتمالين؟ مثلاً، تقديرات الطلاب (ممتاز، جيد، مقبول، راسب).
الحل: نستخدم elif
(اختصار لـ “else if”) لإضافة أسئلة إضافية في السلسلة. بايثون تتحقق منها بالترتيب وتتوقف عند أول شرط صحيح تجده.
score = 85
if score >= 90:
print("التقدير: A")
elif score >= 80: # إذا لم يكن الشرط الأول صحيحًا، اسأل هذا السؤال
print("التقدير: B")
elif score >= 70: # إذا لم يكن الشرطان السابقان صحيحين، اسأل هذا
print("التقدير: C")
else: # إذا لم يكن أي من الشروط السابقة صحيحًا
print("التقدير: F")
د. أدوات طرح الأسئلة: عوامل المقارنة والمنطق
لتكوين أسئلتك (شروطك)، تحتاج إلى أدوات. هذه هي الأدوات التي تستخدمها للمقارنة والربط بين الشروط.
العامل | المعنى | العامل | المعنى |
---|---|---|---|
== |
هل يساوي؟ | and |
و (يجب أن يتحقق الشرطان معًا) |
!= |
هل لا يساوي؟ | or |
أو (يكفي تحقق أحد الشرطين) |
> |
هل أكبر من؟ | not |
ليس (يعكس الحالة: not True تصبح False ) |
< |
هل أصغر من؟ | ||
>= |
هل أكبر من أو يساوي؟ | ||
<= |
هل أصغر من أو يساوي؟ |
هـ. اختصار الشروط: مفهوم “القيم الحقيقية” و”القيم الزائفة”
في بايثون، هناك اختصار ذكي. بدلاً من طرح سؤال كامل، يمكنك أحيانًا وضع القيمة مباشرة في الشرط. بايثون تعتبر بعض القيم False
بطبيعتها، وكل ما عداها يعتبر True
.
القيم التي تعتبر “زائفة” (Falsy) بطبيعتها:
- الرقم صفر (
0
,0.0
) - النص الفارغ (
""
) - القيمة الخاصة
None
(التي تعني “لا شيء”)
لماذا هذا مفيد؟ لأنه يتيح لك التحقق مما إذا كان المستخدم قد أدخل شيئًا أم لا بطريقة أنيقة.
# لنفترض أننا سألنا المستخدم عن اسمه
user_name = input("أدخل اسمك (أو اتركه فارغًا): ")
# بدلاً من كتابة: if user_name != "":
# يمكننا كتابة هذا الكود الأنظف:
if user_name: # السؤال هنا هو: "هل يحتوي هذا المتغير على قيمة حقيقية (غير فارغة)؟"
print(f"أهلاً بك، {user_name}")
else:
print("لم تقم بإدخال اسم.")
و. أسئلة داخل أسئلة: الشروط المتداخلة
يمكنك وضع شرط داخل شرط آخر لاتخاذ قرارات أكثر تعقيدًا. فكر فيها كشجرة قرارات.
age = 22
has_license = False
# السؤال الأول: هل العمر مناسب؟
if age >= 18:
print("أنت كبير بما يكفي للقيادة.")
# الآن، بما أن الشرط الأول تحقق، نسأل سؤالاً داخليًا
if has_license:
print("ويمكنك القيادة بشكل قانوني لأن لديك رخصة.")
else:
print("لكنك تحتاج إلى الحصول على رخصة قيادة أولاً!")
else:
print("أنت لست كبيرًا بما يكفي للقيادة بعد.")
2. الحلقات: تعليم البرنامج كيفية تكرار المهام
المشكلة: ماذا لو أردت طباعة “صباح الخير” 5 مرات؟ أو معالجة 100 اسم مستخدم؟ كتابة الكود 100 مرة أمر غير عملي.
الحل: نستخدم الحلقات (Loops) لتنفيذ نفس كتلة الكود عدة مرات.
أ. حلقة while
: التكرار بشرط
تخيل حلقة while
كحارس أمن يقول لك: “طالما أن شرطًا معينًا متحقق، يمكنك الاستمرار في التكرار”.
# لنطبع الأعداد من 1 إلى 5
count = 1 # 1. نقطة البداية
while count <= 5: # 2. الشرط: استمر طالما أن count أصغر من أو يساوي 5
print(count)
count = count + 1 # 3. خطوة التقدم: نزيد العداد بواحد في كل دورة
تحذير: “خطوة التقدم” (count = count + 1
) هي أهم جزء في حلقة while
. بدونها، سيبقى count
دائمًا 1
، وسيظل الشرط count <= 5
صحيحًا إلى الأبد، مما يدخل برنامجك في حلقة لانهائية (Infinite Loop) ويتجمد.
نمط شائع: while True
للخروج من الداخل
أحيانًا، نريد أن تستمر الحلقة حتى يحدث شيء معين بداخلها. في هذه الحالة، نستخدم while True
ونضع شرط الخروج (break
) بالداخل.
# برنامج يردد ما يكتبه المستخدم حتى يكتب "خروج"
while True:
user_input = input("أدخل أي شيء (أو اكتب 'خروج' للإنهاء): ")
if user_input == "خروج":
break # "اكسر" الحلقة واخرج منها فورًا
print(f"لقد كتبت: {user_input}")
print("إلى اللقاء!")
ب. حلقة for
: التكرار على مجموعة
حلقة for
مثالية عندما يكون لديك مجموعة من العناصر (مثل أحرف نص، أو قائمة أرقام) وتريد أن تفعل شيئًا لكل عنصر فيها، واحدًا تلو الآخر.
المتغير المؤقت: المتغير الذي يأتي بعد كلمة for
(مثل char
أو number
) هو متغير مؤقت. في كل دورة، تضع بايثون تلقائيًا العنصر التالي من المجموعة في هذا المتغير.
-
التكرار على سلسلة نصية:
# في الدورة الأولى، char ستكون "P"، في الثانية "y"، وهكذا for char in "Python": print(char)
-
التكرار باستخدام
range
: دالةrange()
هي آلة لتوليد سلاسل من الأرقام.range(5)
: تولد الأرقام من 0 إلى 4.range(2, 6)
: تولد الأرقام من 2 إلى 5.range(0, 10, 2)
: تولد الأرقام من 0 إلى 8، مع قفزة بمقدار 2.
# مثال: طباعة العد التنازلي من 3 for number in range(3, 0, -1): print(number) print("انطلاق!")
ج. التحكم في الحلقات: break
و continue
break
(مخرج الطوارئ): تُستخدم لإيقاف الحلقة والخروج منها فورًا، حتى لو لم ينتهِ شرطها.continue
(تخطي): تُستخدم لتخطي الدورة الحالية فقط والانتقال مباشرة إلى الدورة التالية في الحلقة.
# مثال: ابحث عن أول رقم يقبل القسمة على 7 وتوقف
for i in range(1, 20):
if i % 7 == 0:
print(f"وجدت أول رقم يقبل القسمة على 7: إنه {i}")
break # اخرج من الحلقة
# مثال: اطبع كل الأرقام ما عدا تلك التي تقبل القسمة على 3
for i in range(1, 11):
if i % 3 == 0:
continue # تخطَ هذه الدورة وانتقل إلى الرقم التالي
print(i)
3. مشروع تطبيقي: التحقق من كلمة المرور
لنطبق ما تعلمناه لبناء برنامج يمنح المستخدم 3 محاولات لإدخال كلمة المرور الصحيحة. هذا المشروع يدمج حلقة for
مع جملة if-else
واستخدام break
.
# كلمة المرور السرية مخزنة في متغير
secret_password = "password123"
# سنمنح المستخدم 3 محاولات، لذا حلقة for مع range(3) مثالية
print("لديك 3 محاولات لإدخال كلمة المرور.")
for attempt_number in range(3):
# نطلب من المستخدم إدخال كلمة المرور في كل محاولة
user_input = input(f"المحاولة رقم {attempt_number + 1}: أدخل كلمة المرور: ")
# نتحقق إذا كانت المحاولة صحيحة
if user_input == secret_password:
print("تم الدخول بنجاح!")
break # المحاولة صحيحة، لا داعي لإكمال الحلقة، اخرج فورًا
else:
print("كلمة مرور خاطئة، حاول مجددًا.")
💡 هل تعلم؟ (طريقة
for...else
الأكثر أناقة)في بايثون، يمكنك استخدام
else
مع حلقةfor
! يتم تنفيذ كتلةelse
فقط إذا انتهت الحلقة بشكل طبيعي (أي لم يتم إيقافها باستخدامbreak
). هذا يلغي الحاجة لمتغيرات التتبع (flags) ويجعل الكود أنظف.
secret_password = "password123"
for attempt_number in range(3):
user_input = input(f"المحاولة {attempt_number + 1}: ")
if user_input == secret_password:
print("تم الدخول بنجاح\!")
break
else:
# هذا الكود لن ينفذ إلا إذا فشلت كل المحاولات الثلاث
print("تم رفض الدخول. لقد استنفدت محاولاتك.")
تمارين تطبيقية
التمرين 1: التحقق من الخصم الخاص
اكتب برنامجًا يقرر ما إذا كان شخص ما مؤهلاً للحصول على خصم خاص على تذاكر السينما. شروط الخصم: يجب أن يكون الشخص طالبًا وعمره بين 18 و 25 عامًا (شاملًا). اطلب من المستخدم الإجابة بـ “نعم” أو “لا” إذا كان طالبًا، واطلب منه عمره، ثم اطبع رسالة مناسبة.
الحل
# سؤال المستخدم عن حالته كطالب وعن عمره
is_student_input = input("هل أنت طالب؟ (أجب بـ 'نعم' أو 'لا'): ").strip().lower()
age_input = input("كم عمرك؟ ")
# تحويل العمر إلى رقم صحيح
age = int(age_input)
# التحقق من الشرط الرئيسي (هل هو طالب؟)
if is_student_input == "نعم":
# شرط متداخل: التحقق من العمر
if age >= 18 and age <= 25:
print("تهانينا! أنت مؤهل للحصول على الخصم الخاص.")
else:
print("عذرًا، الخصم متاح فقط للطلاب الذين تتراوح أعمارهم بين 18 و 25 عامًا.")
else:
print("عذرًا، هذا الخصم مخصص للطلاب فقط.")
التمرين 2: مربع التعليقات
اكتب برنامجًا يطلب من المستخدم كتابة تعليق. إذا كتب المستخدم أي شيء (حتى لو مسافة واحدة) واضغط Enter، يجب على البرنامج طباعة “شكرًا لك على تعليقك!”. أما إذا ضغط المستخدم على Enter دون كتابة أي شيء (نص فارغ)، يجب على البرنامج طباعة “لم تقم بإدخال أي تعليق.”. استخدم مفهوم Truthy/Falsy للتحقق.
الحل
# سؤال المستخدم عن تعليقه
feedback = input("الرجاء كتابة تعليقك هنا: ")
# استخدام مفهوم Truthy للتحقق إذا كان النص غير فارغ
if feedback:
print("شكرًا لك على تعليقك!")
else:
print("لم تقم بإدخال أي تعليق.")
التمرين 3: مدقق الأرقام الموجبة
اكتب برنامجًا يستمر في سؤال المستخدم “أدخل رقمًا موجبًا:” حتى يقوم المستخدم بالفعل بإدخال رقم أكبر من صفر. استخدم حلقة while True
.
الحل
while True:
# سؤال المستخدم داخل الحلقة
number_str = input("أدخل رقمًا موجبًا: ")
number = float(number_str) # نستخدم float ليقبل الأعداد العشرية
# شرط الخروج من الحلقة
if number > 0:
print(f"رائع! {number} هو رقم موجب.")
break # اخرج من الحلقة
else:
print("هذا ليس رقمًا موجبًا. حاول مرة أخرى.")
التمرين 4: العد التنازلي
اكتب برنامجًا يطبع الأعداد من 50 إلى 0، ولكن بقفزات تنازلية بمقدار 5 (أي 50، 45، 40، …، 0). استخدم حلقة for
مع الصيغة الكاملة لدالة range
.
الحل
# نبدأ من 50، نتوقف عند -1 (لأن range لا تشمل النهاية)، والخطوة -5
for number in range(50, -1, -5):
print(number)
التمرين 5: طابع الحروف الساكنة
اكتب برنامجًا يطلب من المستخدم إدخال كلمة، ثم يقوم البرنامج بطباعة الحروف الساكنة (Consonants) في هذه الكلمة فقط، متجاوزًا الحروف المتحركة (Vowels: a, e, i, o, u).
الحل
# سؤال المستخدم عن الكلمة وتحويلها إلى أحرف صغيرة لتسهيل المقارنة
word = input("أدخل كلمة باللغة الإنجليزية: ").lower()
vowels = "aeiou"
print("الحروف الساكنة في الكلمة هي:")
# المرور على كل حرف في الكلمة
for char in word:
# إذا كان الحرف من الحروف المتحركة، تخطَ هذه الدورة
if char in vowels:
continue
# إذا لم يكن كذلك، اطبعه
print(char)
التمرين 6: حاسبة المجموع التراكمي
اكتب برنامجًا يظل يطلب من المستخدم إدخال أرقام ويضيفها إلى مجموع تراكمي. عندما يقوم المستخدم بإدخال الرقم 0
، تتوقف الحلقة ويطبع البرنامج المجموع النهائي لكل الأرقام التي تم إدخالها.
الحل
# تعريف متغير لتخزين المجموع، يبدأ من صفر
total_sum = 0
print("أدخل أرقامًا لجمعها. أدخل 0 للتوقف وحساب المجموع.")
while True:
user_input_str = input("أدخل رقمًا: ")
number = float(user_input_str)
# شرط التوقف
if number == 0:
break
# إضافة الرقم إلى المجموع
total_sum = total_sum + number
print(f"المجموع النهائي لكل الأرقام هو: {total_sum}")
التمرين 7: لعبة تخمين الرقم
اكتب لعبة تخمين رقم بسيطة.
- عرّف متغيرًا
secret_number
بقيمة ثابتة (مثلاً42
). - امنح المستخدم 4 محاولات لتخمين الرقم باستخدام حلقة
for
. - في كل محاولة، أخبر المستخدم إذا كان تخمينه أعلى من اللازم، أقل من اللازم، أو صحيحًا.
- إذا كان التخمين صحيحًا، اطبع رسالة تهنئة واخرج من الحلقة باستخدام
break
. - إذا استنفد المستخدم كل محاولاته، استخدم
for...else
لطباعة رسالة “لقد خسرت!” وتكشف له عن الرقم السري.
الحل
secret_number = 42
print("لعبة تخمين الرقم! لديك 4 محاولات.")
for attempt in range(4):
guess_str = input(f"المحاولة رقم {attempt + 1}: خمن الرقم: ")
guess = int(guess_str)
if guess == secret_number:
print(f"تهانينا! لقد خمنت الرقم الصحيح وهو {secret_number}.")
break
elif guess < secret_number:
print("تخمينك أقل من اللازم.")
else: # guess > secret_number
print("تخمينك أعلى من اللازم.")
else:
# هذا الكود لن يعمل إلا إذا انتهت الحلقة بدون break
print(f"لقد خسرت! الرقم السري كان {secret_number}.")
التمرين 8: طباعة نمط مثلث
اكتب برنامجًا يستخدم حلقة for
متداخلة لطباعة نمط مثلث من النجوم *
كالتالي:
*
**
***
****
*****
الحل
# الحلقة الخارجية تتحكم في عدد الأسطر
for i in range(1, 6): # من 1 إلى 5
# الحلقة الداخلية تتحكم في عدد النجوم في كل سطر
line_of_stars = ""
for j in range(i):
line_of_stars = line_of_stars + "*"
print(line_of_stars)
# حل أسهل باستخدام ميزة ضرب النصوص في بايثون
# for i in range(1, 6):
# print("*" * i)
التمرين 9: فحص الأعداد الأولية
اكتب برنامجًا يسأل المستخدم عن رقم صحيح، ثم يحدد ما إذا كان الرقم أوليًا أم لا. (الرقم الأولي هو رقم أكبر من 1 ولا يقبل القسمة إلا على 1 ونفسه). استخدم حلقة for...else
للتحقق.
الحل
num_str = input("أدخل رقمًا صحيحًا أكبر من 1: ")
num = int(num_str)
if num <= 1:
print("الرقم يجب أن يكون أكبر من 1.")
else:
# نبدأ التحقق من 2 حتى الرقم الذي يسبق الرقم المدخل
for i in range(2, num):
# إذا وجدنا أي قاسم، فالرقم ليس أوليًا
if (num % i) == 0:
print(f"{num} ليس رقمًا أوليًا، لأنه يقبل القسمة على {i}.")
break
else:
# إذا انتهت الحلقة بدون أن نجد أي قاسم، فالرقم أولي
print(f"{num} هو رقم أولي.")
التمرين 10: تحليل جملة
اكتب برنامجًا يطلب من المستخدم إدخال جملة، ثم يقوم بتحليلها وحساب ما يلي:
- عدد الحروف الكلية (بما في ذلك المسافات).
- عدد المسافات.
- عدد الحروف الرقمية (0-9).
الحل
sentence = input("أدخل جملة لتحليلها: ")
# تعريف عدادات تبدأ من صفر
space_count = 0
digit_count = 0
# الحصول على عدد الحروف الكلية باستخدام دالة len()
total_chars = len(sentence)
# المرور على كل حرف في الجملة
for char in sentence:
if char == ' ':
space_count = space_count + 1
elif char.isdigit(): # دالة isdigit() تتحقق إذا كان الحرف رقمًا
digit_count = digit_count + 1
print("\n--- تحليل الجملة ---")
print(f"إجمالي عدد الحروف: {total_chars}")
print(f"عدد المسافات: {space_count}")
print(f"عدد الأرقام: {digit_count}")
4. خلاصة الفصل
لقد قمت بخطوة هائلة! بدأت بفهم البرامج التي تسير في خط مستقيم، والآن يمكنك بناء برامج ذات مسارات متفرعة ودورات متكررة.
if
,elif
, وelse
هي أدواتك لاتخاذ القرارات ورسم مسارات مختلفة في الكود.- مفهوم Truthy/Falsy يمنحك طريقة مختصرة وفعالة لكتابة الشروط.
- حلقة
while
هي حارسك الذي يكرر المهام طالما أن شرطه صحيح. - حلقة
for
هي دليلك الذي يمر على كل عنصر في مجموعة وينفذ عليه مهمة. break
وcontinue
هما أدواتك للتحكم الدقيق في سير الحلقات.
ماذا بعد؟
الآن بعد أن أصبحت قادرًا على التحكم في سير برنامجك، سننتقل في الفصل السادس إلى واحد من أهم مفاهيم البرمجة المنظمة: الدوال (Functions)، حيث سنتعلم كيف نقسم الكود إلى وحدات نظيفة وقابلة لإعادة الاستخدام.