حلقة التكرار while في بايثون (While Loop)
في الدرس السابق، تعلمنا استخدام حلقة for للتكرار على مجموعة عناصر معروفة أو لعدد محدد من المرات. ولكن البرمجة الحقيقية تتضمن حالات لا نعرف فيها مسبقاً عدد مرات التكرار. تخيل أنك تبني نظام تسجيل دخول: يجب أن تستمر في طلب كلمة المرور طالما أن المستخدم يدخل كلمة خاطئة. لا تعرف كم محاولة سيحتاج المستخدم، ربما واحدة أو عشرة أو أكثر.
حلقة while هي الأداة المثالية لهذا النوع من التكرار. بدلاً من القول "كرر 10 مرات"، نقول "استمر في التكرار طالما أن هذا الشرط متحقق". هذا ما يسمى بالتكرار الشرطي أو التكرار غير المحدد (Indefinite Iteration)، لأن عدد التكرارات يعتمد على شرط ديناميكي قد يتغير في أي لحظة.
في هذا الدرس المفصل، ستتعلم كل ما تحتاجه عن حلقة while: من المفاهيم الأساسية إلى التقنيات المتقدمة، مع التركيز على تجنب الأخطاء الشائعة التي يقع فيها المبتدئون.
1. مفهوم التكرار الشرطي
التكرار الشرطي يعني تنفيذ مجموعة من الأوامر مراراً وتكراراً طالما أن شرطاً معيناً يظل صحيحاً. هذا يختلف جوهرياً عن حلقة for التي تتكرر لعدد محدد مسبقاً من المرات.
الفرق الجوهري بين for و while
| حلقة for | حلقة while |
|---|---|
| تكرار محدد (Definite Iteration) | تكرار غير محدد (Indefinite Iteration) |
| نعرف عدد التكرارات مسبقاً | لا نعرف عدد التكرارات مسبقاً |
| تتكرر على عناصر مجموعة | تتكرر بناءً على شرط منطقي |
| مثال: طباعة كل أسماء الطلاب | مثال: طلب كلمة المرور حتى تكون صحيحة |
متى نستخدم while؟
- انتظار إدخال صحيح من المستخدم: طلب البيانات حتى تكون بالتنسيق الصحيح
- الألعاب: استمرار اللعبة طالما اللاعب لم يخسر
- قراءة الملفات: قراءة سطور الملف حتى نهايته
- الخوادم: استقبال الطلبات طالما الخادم يعمل
- المحاكاة: تشغيل المحاكاة حتى تحقق شرط معين
- التحقق من الاتصال: محاولة الاتصال حتى ينجح
2. الصيغة الأساسية لحلقة while
تتكون حلقة while من الكلمة المفتاحية while، يليها شرط منطقي، ثم نقطتان رأسيتان. الكود المراد تكراره يكتب في الأسطر التالية مع إزاحة للداخل، تماماً مثل if و for.
# الصيغة العامة:
# while condition:
# code_block
# update_condition <- مهم جداً!
# مثال أساسي: العد من 1 إلى 5
count = 1
print("بداية العد:")
print("-" * 20)
while count <= 5:
print(f"العدد الحالي: {count}")
count = count + 1 # أو count += 1
print("-" * 20)
print("انتهى العد بنجاح")
print(f"القيمة النهائية للعداد: {count}")
تحليل آلية العمل خطوة بخطوة
- التهيئة: نعين المتغير
countبالقيمة 1 قبل الحلقة - فحص الشرط: هل
count <= 5؟ نعم (1 اصغر من 5)، ندخل الحلقة - تنفيذ الكود: نطبع "العدد الحالي: 1"
- تحديث المتغير: نزيد
countليصبح 2 - العودة للشرط: هل
count <= 5؟ نعم (2 اصغر من 5)، نكرر - الاستمرار: تتكرر الخطوات 3-5 حتى يصبح
countيساوي 6 - الخروج: عندما
count = 6، الشرط6 <= 5خاطئ، نخرج من الحلقة
3. خطر الحلقة اللانهائية (Infinite Loop)
الحلقة اللانهائية هي أحد أكثر الأخطاء شيوعاً وخطورة عند استخدام while. تحدث عندما يظل شرط الحلقة صحيحاً إلى الأبد، مما يتسبب في تعليق البرنامج واستهلاك موارد الحاسوب.
أسباب الحلقة اللانهائية
- نسيان تحديث المتغير: المتغير يبقى على نفس القيمة، فالشرط لا يتغير
- تحديث خاطئ: تحديث المتغير في الاتجاه الخاطئ (الإنقاص بدلاً من الزيادة)
- شرط مستحيل: كتابة شرط لن يصبح أبداً خاطئاً
- خطأ منطقي: استخدام المعامل الخاطئ في الشرط
# مثال 1: نسيان تحديث المتغير
x = 1
while x < 5:
print("سأطبع هذه الجملة إلى الأبد...")
# نسينا كتابة: x += 1
# مثال 2: تحديث في الاتجاه الخاطئ
y = 10
while y > 0:
print(f"القيمة: {y}")
y += 1 # يجب أن تكون y -= 1
# مثال 3: شرط دائماً صحيح
while True:
print("هذا سيستمر للأبد!")
# بدون break لن تتوقف
كيف تتجنب الحلقة اللانهائية؟
- تأكد من تحديث المتغير داخل الحلقة
- تحقق من اتجاه التحديث (زيادة او إنقاص)
- راجع الشرط المنطقي بعناية
- اختبر بقيم حدودية
- استخدم Ctrl+C لإيقاف البرنامج
- أضف حداً أقصى للتكرارات
- استخدم عداداً احتياطياً
- أضف طباعة للتصحيح (debugging)
4. التعامل مع إدخال المستخدم
من أكثر الاستخدامات شيوعاً لحلقة while هو التحقق من صحة إدخال المستخدم. نستمر في طلب الإدخال حتى يقدم المستخدم بيانات صالحة.
# نظام تسجيل دخول بسيط
print("=" * 40)
print(" نظام تسجيل الدخول")
print("=" * 40)
correct_password = "python2024"
user_input = ""
attempts = 0
max_attempts = 3
while user_input != correct_password and attempts < max_attempts:
attempts += 1
remaining = max_attempts - attempts
user_input = input(f"[المحاولة {attempts}/{max_attempts}] أدخل كلمة المرور: ")
if user_input != correct_password:
if remaining > 0:
print(f" خطأ! لديك {remaining} محاولات متبقية.")
else:
print(" خطأ! استنفدت جميع المحاولات.")
if user_input == correct_password:
print("-" * 40)
print(" تم تسجيل الدخول بنجاح!")
print(" مرحباً بك في النظام")
else:
print("-" * 40)
print(" تم قفل الحساب مؤقتاً")
print(" حاول مرة أخرى لاحقاً")
مثال آخر: التحقق من نوع البيانات
# طلب رقم صحيح من المستخدم
print("أدخل عمرك (يجب أن يكون رقماً صحيحاً موجباً)")
valid_input = False
age = 0
while not valid_input:
user_input = input("العمر: ")
# التحقق من أن الإدخال رقم
if user_input.isdigit():
age = int(user_input)
# التحقق من أن العمر منطقي
if 0 < age < 150:
valid_input = True
else:
print(" العمر يجب أن يكون بين 1 و 150")
else:
print(" الرجاء إدخال رقم صحيح فقط")
print(f"\nشكراً! عمرك هو {age} سنة")
5. استخدام else مع حلقة while
من الميزات الفريدة في بايثون إمكانية إضافة else لحلقات التكرار. يتم تنفيذ كتلة else مرة واحدة فقط عندما يصبح شرط الحلقة خاطئاً بشكل طبيعي، أي أن الحلقة اكتملت دون أن يتم إيقافها بـ break.
# مثال: البحث عن رقم في نطاق
target = 7
current = 1
print(f"البحث عن الرقم {target}:")
print("-" * 30)
while current <= 10:
print(f"فحص الرقم {current}...")
if current == target:
print(f" تم العثور على {target}!")
break
current += 1
else:
# يتم تنفيذ هذا فقط إذا لم يتم استخدام break
print(f" لم يتم العثور على {target} في النطاق")
print("-" * 30)
print("انتهى البحث")
else لن تُنفذ إذا تم الخروج من الحلقة باستخدام break. هذا يجعلها مفيدة جداً للتمييز بين اكتمال الحلقة والخروج المبكر.
6. أنماط شائعة لحلقة while
النمط الأول: العداد المتصاعد
i = 0
while i < 10:
print(i)
i += 1
النمط الثاني: العداد المتنازل
countdown = 10
while countdown > 0:
print(f"العد التنازلي: {countdown}")
countdown -= 1
print("انطلاق!")
النمط الثالث: حلقة بشرط علم (Flag)
running = True
while running:
command = input("أدخل أمراً (أو 'خروج' للإنهاء): ")
if command == "خروج":
running = False
else:
print(f"تنفيذ الأمر: {command}")
النمط الرابع: التجميع والحساب
# حساب مجموع أرقام يدخلها المستخدم
total = 0
count = 0
print("أدخل أرقاماً للجمع (أدخل 0 للإنهاء):")
number = int(input("الرقم: "))
while number != 0:
total += number
count += 1
number = int(input("الرقم: "))
if count > 0:
average = total / count
print(f"\nالمجموع: {total}")
print(f"عدد الأرقام: {count}")
print(f"المتوسط: {average:.2f}")
7. تطبيق عملي شامل: لعبة تخمين الرقم
لنجمع كل ما تعلمناه في تطبيق عملي متكامل: لعبة تخمين رقم عشوائي مع عدد محاولات محدود وإحصائيات.
import random
print("=" * 45)
print(" لعبة تخمين الرقم")
print("=" * 45)
print("اخترت رقماً بين 1 و 100. حاول تخمينه!")
print("لديك 7 محاولات فقط.")
print("-" * 45)
secret_number = random.randint(1, 100)
max_attempts = 7
attempts = 0
won = False
while attempts < max_attempts and not won:
attempts += 1
remaining = max_attempts - attempts
try:
guess = int(input(f"\n[المحاولة {attempts}] تخمينك: "))
except ValueError:
print(" الرجاء إدخال رقم صحيح!")
attempts -= 1 # لا نحسب هذه المحاولة
continue
if guess < secret_number:
print(f" منخفض جداً!")
if remaining > 0:
print(f" تلميح: الرقم أكبر من {guess}")
elif guess > secret_number:
print(f" مرتفع جداً!")
if remaining > 0:
print(f" تلميح: الرقم أصغر من {guess}")
else:
won = True
print("\n" + "=" * 45)
if won:
print(f" تهانينا! لقد فزت!")
print(f" الرقم السري: {secret_number}")
print(f" عدد المحاولات: {attempts}")
if attempts == 1:
print(" أداء استثنائي! من المحاولة الأولى!")
elif attempts <= 3:
print(" أداء ممتاز!")
elif attempts <= 5:
print(" أداء جيد!")
else:
print(" نجحت في النهاية!")
else:
print(f" للأسف، لقد خسرت!")
print(f" الرقم السري كان: {secret_number}")
print("=" * 45)
8. أفضل الممارسات والنصائح
- تأكد دائماً من وجود شرط خروج
- حدث المتغيرات التي يعتمد عليها الشرط
- استخدم أسماء متغيرات واضحة ومعبرة
- أضف تعليقات للحلقات المعقدة
- ضع حداً أقصى للتكرارات كإجراء احتياطي
- لا تنس تحديث متغير الشرط
- لا تستخدم
while Trueبدونbreak - لا تعتمد على حدث قد لا يحدث
- تجنب الحلقات المتداخلة العميقة
- لا تهمل معالجة الأخطاء
ملخص الدرس
- حلقة
whileتستخدم للتكرار الشرطي عندما لا نعرف عدد التكرارات مسبقاً - يجب دائماً التأكد من وجود شرط خروج لتجنب الحلقة اللانهائية
- يمكن استخدام
elseمعwhileلتنفيذ كود عند اكتمال الحلقة بشكل طبيعي - تُستخدم
whileبكثرة للتحقق من إدخال المستخدم والألعاب والخوادم
السؤال التالي: كيف يمكننا إيقاف الحلقة قبل اكتمالها او تخطي دورة معينة؟
الخطوة التالية
تعلم كيفية التحكم الدقيق في الحلقات باستخدام break و continue
الدرس التالي: التحكم في الحلقات (break و continue)