1.3 · الحلقات (for وwhile) والاستيعابات

المستوى 1 · أساسيات اللغة

1.3الحلقات (for وwhile) والاستيعابات

الهدف: التكرار بفعالية بـ for وwhile، والتحكم في التدفق بـ break/continue، واكتشاف استيعابات القوائم (list comprehensions).
الوقت المقدّر: 14 دقيقة · قراءة ذاتية · إذا كان لديك 5 دقائق فقط: اقرأ «الأساسي في 30 ثانية» + المخطط.

الأساسي في 30 ثانية

  • تجول for أشياء : for nom in eleves: — دون مؤشرات على الطريقة C ؛ وenumerate() إن كان المؤشر مهما، وrange() للعدّ.
  • while = ما دام، مع خروج : يجب أن يتطور الشرط (عدّاد، break) — وإلا حلقة لانهائية، يقطعها Ctrl+C.
  • الاستيعاب = حلقة بسيطة في سطر واحد : [x*x for x in nombres if x > 0] — محجوز للبسيط، والحلقة الكلاسيكية لما بعده.

حالة مستمرة — نبيل يجول مجيبيه في الجزائر

على نبيل تحية كل مجيب، وإعادة طلب رمز حتى يكون صالحا، ثم استخراج مربعات الدرجات الموجبة. فكتب أولا for i in range(len(noms)) بخطأ مؤشر، ثم while True دون break تدور دون نهاية. فصحح : for nom in noms مباشرة، وwhile بعدّاد يتناقص، واستيعاب بسيط للمربعات. فخرج التقرير في تمريرة واحدة دون حلقة لانهائية.

تتمة الحالة 1.1-1.2 — ينتقل نبيل من القرارات إلى التكرار.

1. for : جُل ولا تعُدّ

في Python نكرر على أشياء (for nom in eleves:) وليس على مؤشرات : فـ for بالمؤشرات على الطريقة C علامة أننا نحارب اللغة. تحتاج مؤشرات ؟ enumerate() ؛ وتحتاج العدّ ؟ range() (تعطي range(5) من 0 إلى 4). تخرج break من الحلقة، وتتجاوز continue دورا.

يستبدل نبيل for i in range(len(noms)) بـ for nom in noms: ويحتفظ بـ enumerate() لترقيم التقرير : فانتهى خطأ المؤشر.

2. while والاستيعابات

تكرر while ما دام الشرط صادقا (مدخل مستخدم، انتظار) : فاضمن الخروج (عدّاد يتطور، break). ويُرشّح استيعاب القائمة (list comprehension) [expression for x in sequence if condition] ويحوّل بمقروئية في سطر واحد — محجوز للبسيط (شرط واحد وتعبير واحد)، وإلا فالحلقة الكلاسيكية تكسب.

يكتب نبيل while tentatives > 0: بتناقص، ثم [s**2 for s in scores if s > 0] للمربعات الموجبة : فتنتهي إعادة الطلب، ويتسع الاستخراج في سطر واحد.

خطأ شائع في الفهم: « for i in range(len(x)) في كل موضع » أو « while True دون خروج، لا بأس ». لا. فالتكرار بالمؤشر حين نريد العناصر يعقّد ويكسر (enumerate() إن كان المؤشر مهما حقا). وwhile لا يتطور شرطها أبدا حلقة لانهائية تحجب البرنامج : فعدّاد أو break أو شرط يتغير — وخروج مضمون دائما.
كرر صحيحا جُل، وما دام، وضُغِط for (جَوِّل) على أشياء،وenumerate للمؤشرwhile (ما دام) شرطيتطور وخروج مضمونالاستيعاب (البسيط) سطر واحدوشرط واحد حدا أقصى
جُل، وما دام، وضُغِط
نص المخطط (SEO / قارئات الشاشة / الترجمة): 1) جُل : يكتب نبيل for nom in noms — الأشياء مباشرة، وenumerate() للترقيم، وrange() للعدّ. 2) كرر : while بعدّاد يتناقص وbreak احتياطية — فيتطور الشرط كل دور. 3) اضغط : استيعاب بسيط للترشيح والتحويل في سطر واحد، وحلقة كلاسيكية متى تعقّد. الدرس : على الأشياء for، ولـ while خروج، وللبسيط استيعاب.

while دون خروج (لا تفعل هذا أبدا)

« برنامجي يدور منذ 20 دقيقة، فهو يفكر كثيرا، أليس كذلك ؟ »
الحكم : لا — فهي while True دون break تدور على لا شيء. Ctrl+C ثم عدّاد.
« وضعت ثلاثة استيعابات متداخلة، فهذه شيفرة كبار. »
الحكم : فهذا لغز وليس شيفرة — لكانت حلقة كلاسيكية تُقرأ في 10 ثوان.

العبرة : حلقة دون خروج كهامستر في عجلته — مشغول جدا، ولم يصل أبدا.

🔎 مثال ملموس — 🔎 مثال ملموس — ثلاث طرق وخيار واحد صحيح لكل واحدة

لكل حلقة إقليمها، كما فعل نبيل في تقريره.

for nom in ["ياسمين", "نبيل"]:
    print(f"مرحبا {nom}")
tentatives = 3
while tentatives > 0:
    tentatives -= 1
carres = [x * x for x in range(10)]
print(carres)  # [0, 1, 4, ..., 81]

القراءة : for مباشرة على العناصر، وwhile بعدّاد يتطور، واستيعاب لبناء القائمة.

الدرس : enumerate() حين يكون المؤشر مهما حقا — وليس range(len()) بالمنعكس أبدا.

مفردات القسم

الحلقة for
تكرر كتلة لكل عنصر من متتالية : for x in sequence. نَجول أشياء لا مؤشرات.

مثال بسيط: المجيبون الذين حياهم نبيل واحدا واحدا.

ما ليس كذلك: for i in range(len(x)) منهجية مع x[i].

رد فعل: for مباشرة ؛ وenumerate() إن كان المؤشر مهما.

range()
تولّد مجال أعداد : تعطي range(5) الأعداد 0 و1 و2 و3 و4. شائعة جدا مع for للعدّ أو التكرار N مرة.

مثال بسيط: مربعات 0 إلى 9 التي حسبها نبيل.

ما ليس كذلك: range(len(liste)) لاسترجاع العناصر.

رد فعل: range() للعدّ وليس للفهرسة.

الحلقة while
تكرر كتلة ما دام الشرط صادقا. وخطر الحلقة اللانهائية إن لم يتغير الشرط أبدا — فاضمن الخروج.

مثال بسيط: إعادة طلب نبيل للرمز حتى مدخل صالح.

ما ليس كذلك: while True دون break ودون شرط يتطور.

رد فعل: عدّاد أو break أو متغير يتغير كل دور.

break / continue
تخرج break من الحلقة فورا ؛ وتتجاوز continue مباشرة إلى التكرار التالي.

مثال بسيط: break نبيل فور إدخال الرمز الصحيح.

ما ليس كذلك: ترك تجوال القائمة كلها وقد وُجد الهدف.

رد فعل: break للإيقاف وcontinue للتجاوز.

استيعاب القائمة
كتابة مضغوطة : [expression for x in sequence if condition] تبني قائمة في سطر واحد، على الطريقة Pythonية.

مثال بسيط: مربعات الدرجات الموجبة التي استخرجها نبيل.

ما ليس كذلك: استيعاب متداخل غير مقروء على ثلاثة مستويات.

رد فعل: البسيط = استيعاب ؛ والمعقد = حلقة كلاسيكية.

في التطبيق — تطبيقيا — كرر بـ for وwhile والاستيعابات

  1. اعرض الأعداد من 1 إلى 10 بـ « for i in range(1, 11) » ثم مربعها. وأضف جدول ضرب عدد مدخل.
  2. اكتب حلقة while تعيد طلب كلمة سر حتى تكون صحيحة (واحرص على تطور الشرط).
  3. استعمل break لإيقاف حلقة فور وقوع شرط، وcontinue لتجاوز الأعداد الزوجية.
  4. حوّل حلقة تبني قائمة مربعات إلى استيعاب قائمة : carres = [n**2 for n in range(10)]. وقارن المقروئية.
صرت تكرر الأفعال بـ for وwhile، وتتحكم في التدفق بـ break/continue، وتكتب أول استيعابات القوائم.

نص جاهز للنطق — اقترح for المباشرة (30 ث)

« أقترح أن نكرر مباشرة على العناصر بدلا من المؤشرات : for nom in noms — فهو أمقروء ويلغي خطأ المؤشر. ونحتفظ بـ enumerate() فقط إن كان الرقم يفيدنا حقا. »

يُقال في مراجعة الشيفرة ؛ واعرض قبل/بعد على الحلقة الحقيقية.

نموذج نسخ ولصق — for مباشرة وwhile بخروج واستيعاب

noms = ["ياسمين", "كريم", "لينا"]
for i, nom in enumerate(noms, start=1):
    print(f"{i}. مرحبا {nom}")
tentatives = 3
while tentatives > 0:
    code = input("الرمز ؟ ")
    if code == "ALGER":
        print("الرمز مقبول")
        break
    tentatives -= 1
carres_positifs = [s ** 2 for s in [3, -1, 4] if s > 0]
print(carres_positifs)  # [9, 16]

تقرير في الجزائر

كما فعل نبيل : for مباشرة + enumerate(start=1) — كل مجيب مُحيَّى ومرقم، وصفر خطأ مؤشر.

إعادة مضمونة

while بعدّاد يتناقص وbreak عند النجاح : فينتهي المدخل دائما.

استخراج في سطر واحد

استيعاب بسيط للدرجات الموجبة : ترشيح + تحويل بمقروئية، دون حلقة من 5 أسطر.

تجاوز مستهدف

continue لتجاهل الزوجيات : نتجاوز دورا بدلا من تداخل if — فيبقى التدفق مسطحا.

✓ ممارسات جيدة

  • كرر على الأشياء (for مباشرة)، وenumerate() إن كان المؤشر يفيد.
  • اضمن خروج كل while (عدّاد، break، شرط يتطور).
  • احجز الاستيعاب للبسيط، والحلقة الكلاسيكية لغيره.

✗ أخطاء شائعة

  • كتابة for i in range(len(x)) منهجيا.
  • إطلاق while True دون break (حلقة لانهائية).
  • تكديس استيعابات متداخلة غير مقروءة.

النقاط الأساسية

  • تجول for متتالية ؛ وتكرر while ما دام شرط صادقا.
  • تولّد range() مجالات الأعداد ؛ وتعطي enumerate() المؤشر + القيمة.
  • تخرج break من الحلقة ؛ وتتجاوز continue إلى التكرار التالي.
  • تبني استيعابات القوائم قائمة في سطر واحد، على الطريقة Pythonية — للبسيط.

تحدي 48 ساعة — طبّق غدا

حوّل حلقة for + range(len()) إلى for مباشرة (النموذج أعلاه)، وأضف خروجا مضمونا إلى while، واضغط بناء قائمة في استيعاب بسيط. وقارن قبل/بعد محليا. تكفي 20 دقيقة.

قائمة الخروج من القسم
  • أَجول بـ for مباشرة — وenumerate() فقط إن كان المؤشر يفيد.
  • لـ while خروج مضمون وbreak/continue في موضعهما.
  • أكتب استيعابات بسيطة مقروءة.
تقييم ذاتي 1-5 : هل تجول حلقاتي أشياء بدلا من مؤشرات ؟هل يمكن لكل while أن تنتهي فعلا ؟

أسئلة شائعة

متى تختار for بدلا من while ؟

استعمل for حين تعرف ما تجوله (قائمة أو مجال أو ملف). واستعمل while حين تكرر حتى شرط تجهل مسبقا عدد تكراراته (مثلا « ما دام المستخدم لم يغادر ») — مع ضمان الخروج.

حلقة while تدور دون نهاية، لماذا ؟

فهي حلقة لانهائية : يبقى الشرط صادقا دائما لأن لا شيء يجعله يتطور في الكتلة. فتأكد أن متغيرا من الشرط يتغير كل دور (عدّاد، break). ويقطع Ctrl+C برنامجا محجوبا.

تحقّق من فهمك

أي كتابة تُفضَّل لتجوال قائمة ؟

موارد إضافية (اختياري، للتعمّق أكثر)

اختبار المستوى 1أسئلة جديدة وأصعب للتحقق من مكتسباتك