حلقة التكرار 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.

basic_while_syntax.py
# الصيغة العامة:
# 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}")
النتيجة
بداية العد: -------------------- العدد الحالي: 1 العدد الحالي: 2 العدد الحالي: 3 العدد الحالي: 4 العدد الحالي: 5 -------------------- انتهى العد بنجاح القيمة النهائية للعداد: 6

تحليل آلية العمل خطوة بخطوة

  1. التهيئة: نعين المتغير count بالقيمة 1 قبل الحلقة
  2. فحص الشرط: هل count <= 5؟ نعم (1 اصغر من 5)، ندخل الحلقة
  3. تنفيذ الكود: نطبع "العدد الحالي: 1"
  4. تحديث المتغير: نزيد count ليصبح 2
  5. العودة للشرط: هل count <= 5؟ نعم (2 اصغر من 5)، نكرر
  6. الاستمرار: تتكرر الخطوات 3-5 حتى يصبح count يساوي 6
  7. الخروج: عندما count = 6، الشرط 6 <= 5 خاطئ، نخرج من الحلقة

3. خطر الحلقة اللانهائية (Infinite Loop)

الحلقة اللانهائية هي أحد أكثر الأخطاء شيوعاً وخطورة عند استخدام while. تحدث عندما يظل شرط الحلقة صحيحاً إلى الأبد، مما يتسبب في تعليق البرنامج واستهلاك موارد الحاسوب.

أسباب الحلقة اللانهائية

  • نسيان تحديث المتغير: المتغير يبقى على نفس القيمة، فالشرط لا يتغير
  • تحديث خاطئ: تحديث المتغير في الاتجاه الخاطئ (الإنقاص بدلاً من الزيادة)
  • شرط مستحيل: كتابة شرط لن يصبح أبداً خاطئاً
  • خطأ منطقي: استخدام المعامل الخاطئ في الشرط
تحذير: الكود التالي يحتوي على حلقة لانهائية. لا تقم بتشغيله إلا إذا كنت تعرف كيف توقفه باستخدام Ctrl+C في الطرفية.
infinite_loop_examples.py
# مثال 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 هو التحقق من صحة إدخال المستخدم. نستمر في طلب الإدخال حتى يقدم المستخدم بيانات صالحة.

password_validation.py
# نظام تسجيل دخول بسيط
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("   حاول مرة أخرى لاحقاً")

مثال آخر: التحقق من نوع البيانات

number_validation.py
# طلب رقم صحيح من المستخدم
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.

while_else_example.py
# مثال: البحث عن رقم في نطاق
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("انتهى البحث")
النتيجة
البحث عن الرقم 7: ------------------------------ فحص الرقم 1... فحص الرقم 2... فحص الرقم 3... فحص الرقم 4... فحص الرقم 5... فحص الرقم 6... فحص الرقم 7... تم العثور على 7! ------------------------------ انتهى البحث
ملاحظة مهمة: كتلة else لن تُنفذ إذا تم الخروج من الحلقة باستخدام break. هذا يجعلها مفيدة جداً للتمييز بين اكتمال الحلقة والخروج المبكر.

6. أنماط شائعة لحلقة while

النمط الأول: العداد المتصاعد

ascending_counter.py
i = 0
while i < 10:
    print(i)
    i += 1

النمط الثاني: العداد المتنازل

descending_counter.py
countdown = 10
while countdown > 0:
    print(f"العد التنازلي: {countdown}")
    countdown -= 1
print("انطلاق!")

النمط الثالث: حلقة بشرط علم (Flag)

flag_pattern.py
running = True
while running:
    command = input("أدخل أمراً (أو 'خروج' للإنهاء): ")
    if command == "خروج":
        running = False
    else:
        print(f"تنفيذ الأمر: {command}")

النمط الرابع: التجميع والحساب

accumulator_pattern.py
# حساب مجموع أرقام يدخلها المستخدم
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. تطبيق عملي شامل: لعبة تخمين الرقم

لنجمع كل ما تعلمناه في تطبيق عملي متكامل: لعبة تخمين رقم عشوائي مع عدد محاولات محدود وإحصائيات.

number_guessing_game.py
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)
المحرر الذكي

اكتب الكود وشاهد النتيجة فوراً

جرب الآن مجاناً
قناة ديف عربي

تابع أحدث الدروس والتحديثات مباشرة على واتساب

انضم الآن