حلقات while — التكرار طالما تحقق الشرط
تكرار العمل، كيف تحدث الحلقات اللانهائية وكيفية إيقافها، أوامر break و continue، وإعادة السؤال حتى إدخال قيمة صحيحة.
كيف تريد أن تتعلم؟
المشكلة التي نقوم بحلها
في الفصل السابق تعلّمنا اكتشاف الإدخال غير الصالح — عندما يكتب أحدهم twenty، يستطيع البرنامج أن يقول "هذا ليس رقماً".
لكن ماذا يفعل بعد ذلك؟ يتوقف. وعلى المستخدم أن يشغّل البرنامج كله من جديد. لا يوجد برنامج حقيقي يتصرف هكذا — بل يسأل مرة أخرى، ويستمر في السؤال حتى يحصل على إجابة صالحة.
هذا هو عمل الحلقات (loops): تكرار العمل نفسه ما دام ذلك ضرورياً. اليوم نتعلم while، التي تعمل ما دام شرط ما صحيحاً.
وتنتظرك اليوم تجربة جديدة أيضاً: برنامج لا يتوقف، ونص يتسارع في الطرفية. لا داعي للخوف — ستتعلم كيف توقفه في هذا الفصل نفسه.
في نهاية هذا الفصل ستكون قادراً على
- كتابة حلقة
whileومعرفة متى ستتوقف - فهم سبب حدوث الحلقات اللانهائية، وإيقاف إحداها بـ
Ctrl + C - تجميع مجموع أو عدد داخل حلقة
- استخدام
breakوcontinueفي المكان الصحيح - الاستمرار في السؤال حتى يصبح الإدخال صالحاً
المتطلبات السابقة: اتخاذ القرارات — if و elif و else.
أبسط حلقة
count = 3
while count > 0:
print(count)
count = count - 1
print("Go")3
2
1
Goيبدو الشكل تماماً مثل if — شرط، ونقطتان، وكتلة مُزاحة. هناك فرق واحد، وهو كل شيء: if تفحص الشرط مرة واحدة؛ أما while فتفحصه من جديد في كل مرة تنتهي فيها الكتلة.
ما فعله البرنامج أعلاه:
countتساوي3. الشرط3 > 0صحيح → نُفّذت الكتلة، وطُبع3، وأصبحتcountتساوي2- الشرط مرة أخرى:
2 > 0صحيح → طُبع2، وأصبحتcountتساوي1 - الشرط مرة أخرى:
1 > 0صحيح → طُبع1، وأصبحتcountتساوي0 - الشرط مرة أخرى:
0 > 0خاطئ → انتهت الحلقة وانتقل التنفيذ إلى ما بعدها
كل حلقة while تعمل بشكل صحيح لها ثلاثة أجزاء، وتحتاج إليها كلها:
- قيمة ابتدائية — قبل الحلقة (
count = 3) - شرط — متى تستمر (
count > 0) - تغيير — شيء في الداخل سيجعل الشرط خاطئاً في النهاية (
count = count - 1)
الحلقات اللانهائية
من المفيد أن ترى ما يحدث عندما يغيب الجزء الثالث:
count = 3
while count > 0:
print(count)هذا يطبع 3 إلى الأبد. count لا تتغير أبداً، لذلك لا يصبح count > 0 خاطئاً أبداً.
طريقة الإيقاف: اضغط Ctrl + C في الطرفية. يتوقف فوراً ويعرض شيئاً كهذا:
Traceback (most recent call last):
File "D:\python-lab\lesson-10\loop.py", line 4, in <module>
print(count)
KeyboardInterruptسيُظهر سطر File المسار الكامل لملفك، ورقم السطر يعتمد على اللحظة التي ضغطت فيها المفاتيح بالضبط. KeyboardInterrupt تعني أنك أنت من أوقفه. هذا ليس خطأً في كودك، بل قرارك أنت.
الحلقات اللانهائية جزء من التعلّم. كل مبرمج كتب واحدة، وما زال يكتب. لا داعي للخوف — معرفة Ctrl + C تجعلها مجرد إزعاج بسيط. عند كتابة حلقة، اسأل نفسك مرة واحدة فقط: "كيف سيصبح هذا الشرط خاطئاً؟" إذا لم تستطع الإجابة، فلن تتوقف الحلقة.التجميع
أكثر عمل شائع للحلقة هو تجميع شيء ما — مجموع، أو عدد، أو أكبر قيمة:
total = 0
number = 1
while number <= 5:
total = total + number
number = number + 1
print("Sum of 1 to 5:", total)Sum of 1 to 5: 15يسمّى total المُجمِّع (accumulator) — الوعاء الذي تجمع فيه. لاحظ أنه يبدأ خارج الحلقة، من 0. لو بدأ داخلها لعاد إلى الصفر في كل دورة، ولم يبقَ في النهاية إلا الرقم الأخير.
break — اخرج الآن
break تنهي الحلقة فوراً، مهما قال الشرط:
number = 1
while number <= 100:
if number % 7 == 0:
print("First multiple of 7:", number)
break
number = number + 1First multiple of 7: 7قال الشرط أن تستمر حتى 100، لكن العمل انتهى لحظة ظهور 7 — فلا معنى للدوران 93 مرة أخرى.
تجعل break نمطاً مفيداً جداً ممكناً — كتابة True مكان الشرط، والخروج من المكان المناسب في الداخل:
while True:
answer = input("Type 'quit' to exit: ").strip().lower()
if answer == "quit":
print("Goodbye")
break
print(f"You typed: {answer}")Type 'quit' to exit: hello
You typed: hello
Type 'quit' to exit: QUIT
Goodbyewhile True تعني "استمر إلى الأبد"، لذلك فإن وجود break في الداخل إلزامي — وإلا فهي حلقة لانهائية.
continue — تخطَّ هذه الدورة
continue لا تنهي الحلقة؛ بل تتخطى بقية الكتلة وتنتقل مباشرة إلى الدورة التالية:
number = 0
while number < 10:
number = number + 1
if number % 2 == 0:
continue
print(number)1
3
5
7
9مع كل رقم زوجي نُفّذت continue، فتُخطي print.
في كتابةcontinueفخ. إذا كان السطر الذي يدفع الشرط إلى الأمام (number = number + 1) يأتي بعدcontinue، فإنcontinueستتخطاه — وتعلق الحلقة هناك إلى الأبد. لهذا جاء سطر الزيادة أولاً في الكود أعلاه. كلما استخدمتcontinue، تحقق من هذا الترتيب.
أخيراً: السؤال حتى يصبح الإدخال صالحاً
هذا ما كنا ننتظره منذ فصلين:
while True:
raw = input("Your age: ").strip()
if raw.isdigit():
age = int(raw)
break
print("Please type a whole number, digits only.")
print(f"Thank you. Age recorded as {age}.")Your age: twenty
Please type a whole number, digits only.
Your age: 22.5
Please type a whole number, digits only.
Your age: 22
Thank you. Age recorded as 22.هذا هو النمط الذي ستستخدمه طوال حياتك العملية: حلقة لا نهائية، وتحقق في الداخل، و break عندما يكون الإدخال سليماً، ورسالة ثم دورة جديدة عندما لا يكون كذلك. لم يعد البرنامج ينهار عند الإدخال الخاطئ، ولا يضطر المستخدم إلى البدء من جديد.
مثال كامل
shopping.py:
# Keep taking item prices until the user is done, then summarise
total = 0.0
item_count = 0
print("Enter item prices. Type 'done' to finish.")
while True:
entry = input("Price: ").strip().lower()
if entry == "done":
break
if entry == "":
print(" Nothing typed — try again.")
continue
# Accept only digits and at most one decimal point
if entry.replace(".", "", 1).isdigit():
price = float(entry)
total = total + price
item_count = item_count + 1
print(f" Added {price:.2f}. Running total {total:.2f}")
else:
print(f" '{entry}' is not a price. Try again.")
print()
if item_count == 0:
print("No items were entered.")
else:
average = total / item_count
print(f"Items : {item_count}")
print(f"Total : {total:.2f}")
print(f"Average : {average:.2f}")Enter item prices. Type 'done' to finish.
Price: 120
Added 120.00. Running total 120.00
Price: abc
'abc' is not a price. Try again.
Price: 85.5
Added 85.50. Running total 205.50
Price: done
Items : 2
Total : 205.50
Average : 102.75ثلاثة أشياء تعمل معاً هنا، وكلها من مادة اليوم:
break— الخروج من الحلقة عندما يكتب المستخدمdonecontinue— تخطي البقية والسؤال من جديد عند سطر فارغ- المُجمِّعات —
totalوitem_countيبدآن كلاهما خارج الحلقة ويزدادان داخلها
فكّر لماذا نحتاج إلى if item_count == 0 في النهاية. إذا كتب أحدهم done فوراً دون إدخال أي شيء، تكون item_count تساوي 0، وكانت total / item_count ستكسر البرنامج بـ ZeroDivisionError. قبل استخدام أي شيء جمّعته الحلقة، اطرح السؤال في كل مرة: "هل جُمّع أي شيء أصلاً؟"
حالات الخطأ الشائعة وحلولها
البرنامج لا يتوقف، والنص يتسارع اضغط Ctrl + C. ثم تأكد أن جسم الحلقة يحتوي على السطر الذي يدفع الشرط إلى الأمام، وأنه لا يقع بعد continue.
الحلقة لم تُنفَّذ أبداً كان الشرط خاطئاً من البداية. قارن القيمة الابتدائية بالشرط — while count > 0 مع البدء من count = 0 لن تدخل أبداً.
تُنفَّذ مرة زائدة أو مرة ناقصة حدث خلط بين < و <=. بدءاً من n = 1، تُنفَّذ while n < 5 أربع مرات (عندما تكون n تساوي 1 و 2 و 3 و 4)، و while n <= 5 خمس مرات. غيّر القيمة الابتدائية ويتغير العدد أيضاً — بدءاً من n = 0، تُنفَّذ while n < 5 خمس مرات. لذلك افحص القيمة الابتدائية والشرط معاً دائماً.
IndentationError: expected an indented block after 'while' statement السطر الذي بعد while غير مُزاح.
NameError بعد الحلقة — المتغير غير معروف أُنشئ المتغير داخل الحلقة فقط، وإذا لم تُنفَّذ الحلقة أبداً فإنه لم يُنشأ أصلاً. أعطِ كل متغير تحتاجه بعد الحلقة قيمة ابتدائية قبلها.
المجموع خاطئ في نهاية الحلقة تحقق مما إذا كان المُجمِّع يُهيَّأ داخل الحلقة. يجب أن يكون سطر total = 0 خارجها.
الخطوة ٤ من ٦ — التوقع
تحقّق من فهمك
ما الناتج الكامل لهذه الحلقة؟
count = 3
while count > 0:
print(count)
count = count - 1
print("Go")- A2 1 0 Go
- B3 2 1 0 Go
- C3 Go
- D3 2 1 Go
هذا البرنامج لا يتوقف أبداً. ما الناقص؟
total = 0
number = 1
while number <= 5:
total = total + number
print(total)- Aيجب أن تكون `while` جملة `if`
- Bلا يوجد `number = number + 1` داخل الحلقة، لذلك لا يصبح الشرط خاطئاً أبداً
- Cتغيير `<=` إلى `<` في الشرط سيجعلها تتوقف
- Dلم تُهيَّأ `total` داخل الحلقة
مع وجود continue، ماذا تطبع هذه الحلقة؟
number = 0
while number < 5:
number = number + 1
if number == 3:
continue
print(number)- A1 2 4 5
- B1 2 3 4 5
- C1 2 4
- D1 2
الإجابة تتطلب حساباً
سجّل الدخول للتحقق من إجاباتك
الأسئلة موجودة أعلاه، والتفكير في إجاباتها ذهنياً هو الجزء المهم. سجّل الدخول لرؤية الإجابات والتفسيرات والتلميحات ذات المستويات الثلاثة.
دورك الآن
اكتب لعبة تخمين أرقام، guess.py:
- حدّد رقماً سرياً في الكود، بين 1 و 100
- اطلب من المستخدم أن يخمّن، وقل له في كل مرة "أعلى" أو "أقل"
- عند التخمين الصحيح، هنّئه واخرج من الحلقة
- اطبع عدد التخمينات التي احتاجها
- إذا كتب شيئاً ليس رقماً، يجب ألا ينكسر البرنامج — اطبع رسالة واسأل مرة أخرى
- بعد سبع محاولات تنتهي اللعبة، ويُكشف الرقم السري
الشرط السادس هو الذي سيجعلك تفكر: يمكن لحلقتك الآن أن تنتهي لسببين مختلفين — تخمين صحيح، أو نفاد المحاولات. طريقة ترتيبك لهذين المخرجين هي السؤال الحقيقي في هذا التمرين. وعندما يعمل، اقرأ كودك مرة أخرى واسأل: هل توجد حالة يمكن أن تصل إليها هذه الحلقة فتستمر إلى الأبد؟
في هذه المهمة المزيد
ما قرأته أعلاه هو المهمة كاملة — لم يُحذف منها شيء. يضيف Pro:
- ما يحدث فعلياً في الكواليس — كيف ينفذ بايثون هذا الكود
- الحل الكامل للتمرين مشروحاً خطوة بخطوة
- تمارين إضافية أكثر صعوبة وتحدياً
- أسئلة المقابلات الوظيفية حول هذا الموضوع مع نموذج الإجابة
الخطوة ٦ من ٦
التحدي — اختبار الفصل
عشرة أسئلة متدرجة من السهل إلى الصعب. الأسئلة الأخيرة صعبة عن قصد.
سجّل الدخول لأداء الاختبار