2.12. الحلقات#

تُشغّل الحلقة الكتلة نفسها من الشيفرة بشكل متكرّر. لدى Python شكلان: while التي تستمر طالما بقي الشرط صحيحًا، و for التي تسير عبر عناصر تسلسل.

Side-by-side flowcharts. while: test the condition, run the body if true, repeat. for: take the next item from the iterable, run the body, repeat until exhausted.

تستمر while في اختبار شرط؛ بينما تسير for عبر تسلسل حتى يُستنفد.#

2.12.1. حلقات while#

تختبر حلقة while شرطها قبل كل تكرار وتُشغّل الجسم حتى يصبح الاختبار خاطئًا:

count = 0
while count < 5:
    print(count)
    count += 1

المخرجات:

0
1
2
3
4

إذا كان الشرط صحيحًا في البداية ولم يصبح خاطئًا أبدًا، فإن الحلقة تعمل إلى ما لا نهاية. while True: هي الصيغة المعيارية للحلقة الرئيسية، ويُخرَج منها صراحةً باستخدام break:

while True:
    step()
    if done():
        break

2.12.2. حلقات for#

تسير حلقة for عبر عناصر كائن قابل للتكرار -- قائمة أو صف (tuple) أو سلسلة نصية أو بايتات أو قاموس أو أي شيء آخر يدعم التكرار:

for fruit in ["apple", "banana", "cherry"]:
    print(fruit)

المخرجات:

apple
banana
cherry

الشكل نفسه يعمل على سلسلة نصية، حيث يكون كل عنصر سلسلةً من حرف واحد:

for letter in "OpenMV":
    print(letter)

المخرجات:

O
p
e
n
M
V

التكرار على قاموس مباشرةً ينتج مفاتيحه، بترتيب الإدراج:

for key in {"a": 1, "b": 2}:
    print(key)

المخرجات:

a
b

يربط كل تمرير متغيّر الحلقة (fruit أو letter أو key) بالعنصر التالي. وبعد انتهاء الحلقة، يحتفظ المتغيّر بالقيمة من التكرار الأخير.

2.12.3. range#

للحلقات على نطاق عددي، استخدم range():

  • range(stop) -- 0، 1، ...، stop - 1.

  • range(start, stop) -- start، start + 1، ...، stop - 1.

  • range(start, stop, step) -- بخطوة مخصّصة (القيم السالبة تعدّ تنازليًا).

for i in range(5):           # 0, 1, 2, 3, 4
    print(i)

for i in range(2, 8, 2):     # 2, 4, 6
    print(i)

for i in range(10, 0, -1):   # 10, 9, ..., 1
    print(i)

تُنتج range() القيم بشكل كسول -- فهي لا تبني قائمة في الذاكرة. للحصول على list فعلية، غلّفها: list(range(10)).

2.12.4. enumerate#

عندما تحتاج الحلقة إلى المؤشّر والعنصر معًا، تُنتج enumerate() أزواج (index, item):

for i, name in enumerate(["a", "b", "c"]):
    print(i, name)
# 0 a
# 1 b
# 2 c

ابدأ المؤشّر من قيمة غير الصفر بتمرير وسيط ثانٍ: enumerate(items, start=1).

2.12.5. zip#

للسير عبر اثنين (أو أكثر) من الكائنات القابلة للتكرار بشكل متزامن، استخدم zip(). فهي تنتج صفًا (tuple) واحدًا لكل موضع وتتوقف عند أقصر إدخال:

names  = ["alice", "bob", "carol"]
scores = [88, 92, 70]

for name, score in zip(names, scores):
    print(name, score)

المخرجات:

alice 88
bob 92
carol 70

2.12.6. الإسناد المضمّن باستخدام :=#

عامل الفظ (walrus) := هو إسناد يُعدّ أيضًا تعبيرًا. فهو يربط اسمًا ويُقيَّم إلى القيمة نفسها في الوقت نفسه. في حلقة while، يطوي هذا النمط الشائع "اقرأ، تحقّق، الجسم" في سطر واحد:

# without walrus
value = next_value()
while value is not None:
    process(value)
    value = next_value()

# with walrus
while (value := next_value()) is not None:
    process(value)

يؤدّي الشكلان الشيء نفسه. استخدم := عندما يضرّ تكرار الإسناد فعلًا بقابلية القراءة؛ لا تستخدمه لمجرد التباهي بالذكاء. والأقواس مطلوبة في معظم المواضع للحفاظ على وضوح التعبير.