الحلقة تكرّر كتلة من الكود. في بايثون نوعان: for تمرّ على عناصر شيء موجود (قائمة، نص، مجال أرقام)، و**while** تكرّر ما دام شرط صحيحًا.
for: لكل عنصر
languages = ["HTML", "CSS", "Python"]
for lang in languages:
print(f"أتعلّم {lang}")
اقرأها حرفيًّا: "لكل lang في languages، اطبع...". في كل دورة يأخذ lang العنصر التالي، وتنتهي الحلقة حين تنفد العناصر. وتعمل for مع أي شيء قابل للمرور عليه:
for ch in "سلام": # أحرف نص
print(ch, end=" ")
print()
prices = {"كتاب": 12, "قلم": 1}
for item, price in prices.items(): # أزواج قاموس
print(item, price)
range: مجال أرقام
حين تحتاج تكرارًا بعدد محدّد، range تولّد الأرقام:
for i in range(5):
print(i, end=" ") # 0 1 2 3 4
print()
for i in range(1, 6):
print(i, end=" ") # 1 2 3 4 5
print()
for i in range(10, 0, -3):
print(i, end=" ") # 10 7 4 1
print()
كالتقطيع في النصوص، النهاية غير مشمولة: range(5) خمسة أرقام تبدأ من صفر. تفاصيل range وسبب كفاءتها في درس lambda وrange.
الرقم والعنصر معًا
names = ["سارة", "أحمد", "ليلى"]
for i, name in enumerate(names, start=1):
print(f"{i}. {name}")
لا تكتب for i in range(len(names)): ثم names[i]؛ enumerate تعطيك الاثنين مباشرة، وzip تمرّ على قائمتين معًا (درس enumerate وzip).
مثال: المجموع والأكبر
scores = [72, 91, 85, 64, 88]
total = 0
highest = scores[0]
for s in scores:
total += s
if s > highest:
highest = s
print(f"المجموع {total}، المعدّل {total / len(scores):.1f}، الأعلى {highest}")
print(sum(scores), max(scores)) # نفس النتيجة بدوال جاهزة
نمط المجمِّع (Accumulator): متغيّر يبدأ قبل الحلقة ويتحدّث في كل دورة. ستكتبه كثيرًا، حتى لو كانت sum وmax تكفي هنا.
while: ما دام الشرط صحيحًا
balance = 1000
years = 0
while balance < 2000:
balance *= 1.07 # ربح 7% سنويًّا
years += 1
print(f"يتضاعف المبلغ بعد {years} سنوات") # 11
while حين لا تعرف عدد الدورات مسبقًا. والمسؤولية عليك: شيء داخل الحلقة يجب أن يقرّبها من جعل الشرط خاطئًا، وإلا دارت للأبد. إن علق برنامجك، أوقفه بـ Ctrl+C.
حلقة حتى إدخال صحيح
attempts = iter(["abc", "-5", "42"]) # محاكاة لما يكتبه المستخدم
while True:
text = next(attempts) # في الواقع: text = input("العمر: ")
if text.isdigit() and int(text) > 0:
age = int(text)
break
print(f"'{text}' غير صالح، حاول مجدّدًا")
print("العمر:", age)
while True مع break نمط شائع حين يكون شرط الخروج في منتصف الحلقة لا في أولها.
break وcontinue وelse
numbers = [4, 7, -1, 9, 12]
for n in numbers:
if n < 0:
print("قيمة سالبة، توقّف")
break # اخرج من الحلقة كلها
if n % 2:
continue # تخطَّ بقية هذه الدورة فقط
print("زوجي:", n)
وميزة خاصة ببايثون: else بعد الحلقة تُنفَّذ إن انتهت الحلقة بلا break:
users = ["sara", "ahmad", "laila"]
target = "omar"
for u in users:
if u == target:
print("وُجد")
break
else:
print("غير موجود") # لم يحدث break
مفيدة للبحث: "إن لم تجده بعد المرور على الكل". اقرأ else هنا كـ "لم ينكسر".
حلقات متداخلة
for row in range(1, 4):
for col in range(1, 4):
print(row * col, end="\t")
print()
الداخلية تكتمل كاملة في كل دورة من الخارجية: جدول ضرب 3×3 = 9 دورات. انتبه للتكلفة: حلقتان على ألف عنصر مليون دورة.
جرّب بنفسك
📥 المدخلات (input) — قيمة في كل سطر
أخطاء شائعة
- تعديل قائمة أثناء المرور عليها (
removeداخلforعلى نفس القائمة): تتخطّى عناصر بصمت. مرّ على نسخةfor x in items[:]، أو ابنِ قائمة جديدة (Comprehensions). whileبلا تحديث للمتغيّر: حلقة لا تنتهي.range(len(x))لتحصل على العنصر: استخدمfor item in xأوenumerate.- الخطأ بواحد:
range(1, 10)تتوقّف عند 9. للعشرة:range(1, 11). - إزاحة
printخطأ: داخل الحلقة يُطبع كل دورة، وخارجها مرة واحدة. انتبه لمكان السطر.
🎯 التالي: الدوال: تنظيم الكود وإعادة استخدامه.