📘 درسنامه حلقه‌ها (Loops) در پایتون

آموزش جامع تکرار در برنامه‌نویسی: حلقه for، حلقه while، تابع range، حلقه روی لیست و رشته، دستورات break و continue، حلقه‌های تودرتو (Nested Loops)، List Comprehension — به همراه مثال‌های متعدد، تمرینات عملی و پروژه‌های کاربردی | آکادمی غیاثی

🔰 مقدمه: حلقه‌ها در برنامه‌نویسی

حلقه‌ها به ما اجازه می‌دهند که یک بلاک کد را چندین بار اجرا کنیم. این یکی از قدرتمندترین ابزارهای برنامه‌نویسی است که باعث می‌شود کد ما کوتاه‌تر و کارآمدتر باشد! بدون حلقه‌ها، اگر بخواهیم یک کار را ۱۰۰ بار تکرار کنیم، باید ۱۰۰ بار همان کد را بنویسیم. با حلقه‌ها، فقط یک بار می‌نویسیم و به پایتون می‌گوییم چند بار اجرا کند.

💡 نکته مهم: در پایتون دو نوع حلقه اصلی داریم: for و while. هر کدام برای کاربردهای خاصی مناسب هستند. حلقه for برای زمانی که تعداد دفعات تکرار را از قبل می‌دانیم مناسب است، و حلقه while برای زمانی که تکرار تا رسیدن به یک شرط خاص ادامه پیدا می‌کند.

🔄 حلقه for و تابع range

حلقه for برای تکرار روی یک دنباله (مثل لیست، تاپل، رشته یا range) استفاده می‌شود. تابع range(n) اعداد ۰ تا n-1 را تولید می‌کند. همچنین می‌توان از range(start, stop, step) با پارامترهای شروع، پایان و گام استفاده کرد.

🐍 کد: حلقه for ساده با range
# چاپ اعداد 0 تا 4
for i in range(5):
    print(f"عدد: {i}")

print("حلقه تمام شد!")
📝 توضیح: در این کد، متغیر i به ترتیب مقادیر 0، 1، 2، 3، 4 را می‌گیرد و در هر مرحله یک بار دستور print اجرا می‌شود. دقت کنید که range(5) عدد 5 را شامل نمی‌شود.
🐍 کد: range با شروع، پایان و گام
# range(شروع, پایان, گام) — اعداد فرد 1 تا 10
for i in range(1, 11, 2):
    print(f"عدد: {i}")
📝 توضیح: در اینجا range(1, 11, 2) به معنی: از 1 شروع کن، تا قبل از 11 ادامه بده (یعنی 10)، و هر بار 2 تا 2 تا جلو برو. بنابراین اعداد فرد 1، 3، 5، 7، 9 چاپ می‌شوند.

📋 حلقه for روی لیست‌ها و رشته‌ها

حلقه for می‌تواند مستقیماً روی عناصر یک لیست یا کاراکترهای یک رشته تکرار شود.

🐍 کد: for روی لیست و رشته
# حلقه روی لیست
fruits = ["سیب", "پرتقال", "موز", "انگور"]
print("میوه‌ها:")
for fruit in fruits:
    print(f"- {fruit}")

print("\n" + "="*20 + "\n")

# حلقه روی رشته
word = "پایتون"
print("حروف کلمه پایتون:")
for char in word:
    print(char)
📝 توضیح: در حلقه اول، متغیر fruit به ترتیب هر عنصر لیست را می‌گیرد. در حلقه دوم، متغیر char به ترتیب هر کاراکتر رشته را می‌گیرد. این روش بسیار خوانا و طبیعی است.

🔁 حلقه while

حلقه while تا زمانی که شرط آن درست باشد، ادامه پیدا می‌کند. باید مراقب باشیم که شرط در نهایت False شود تا حلقه بی‌نهایت نشود!

🐍 کد: حلقه while ساده
# شمارنده
count = 0
while count < 5:
    print(f"شمارنده: {count}")
    count += 1  # مهم: افزایش شمارنده

print("حلقه تمام شد!")
print(f"مقدار نهایی شمارنده: {count}")
⚠️ هشدار مهم: اگر در حلقه while متغیر شرط را تغییر ندهید، حلقه برای همیشه ادامه پیدا می‌کند و برنامه شما قفل می‌شود (حلقه بی‌نهایت). در کد بالا، count += 1 باعث می‌شود که بعد از ۵ بار تکرار، شرط count < 5 نادرست شود و حلقه متوقف گردد.
📝 توضیح: حلقه while زمانی مناسب است که تعداد دفعات تکرار را از قبل نمی‌دانیم و می‌خواهیم تا رسیدن به یک شرط خاص ادامه دهیم. مثال: منتظر ماندن تا کاربر پاسخ درست را وارد کند.

⏸️ دستورات break و continue

break: حلقه را فوراً متوقف می‌کند و از آن خارج می‌شود. continue: یک تکرار را رد می‌کند و به سراغ تکرار بعدی می‌رود.

🐍 کد: مثال break
# جستجو در لیست
numbers = [12, 45, 7, 23, 56, 89, 34]

search_num = int(input("عدد مورد نظر را وارد کنید: "))

for num in numbers:
    if num == search_num:
        print(f"عدد {search_num} پیدا شد!")
        break
else:
    print(f"عدد {search_num} در لیست یافت نشد.")
📝 توضیح break: در این کد، به محض اینکه عدد مورد نظر پیدا شود، break اجرا می‌شود و حلقه بلافاصله متوقف می‌شود. بخش else بعد از حلقه فقط زمانی اجرا می‌شود که حلقه به طور عادی به پایان رسیده باشد (بدون break).
🐍 کد: مثال continue
# چاپ فقط اعداد زوج
print("اعداد زوج بین 1 تا 10:")
for i in range(1, 11):
    if i % 2 != 0:  # اگر عدد فرد بود
        continue  # رد کن و برو سراغ بعدی
    print(i)
📝 توضیح continue: در این کد، هرگاه به عدد فرد برسیم، continue اجرا می‌شود و دستورات بعدی در همان تکرار (یعنی print(i)) نادیده گرفته می‌شود و حلقه به سراغ عدد بعدی می‌رود. در نتیجه فقط اعداد زوج چاپ می‌شوند.

🏗️ حلقه‌های تودرتو (Nested Loops)

می‌توانیم یک حلقه را داخل حلقه دیگر قرار دهیم. این کار برای کارهایی مثل چاپ جداول، ماتریس‌ها و الگوها بسیار مفید است.

🐍 کد: جدول ضرب با حلقه تودرتو
# چاپ جدول ضرب کامل (1 تا 5)
print("جدول ضرب کامل (1 تا 5):")
for i in range(1, 6):
    for j in range(1, 6):
        print(f"{i}×{j}={i*j}", end="\t")
    print()  # خط جدید بعد از هر سطر
📝 توضیح: حلقه بیرونی (i) برای سطرهاست (از 1 تا 5). برای هر مقدار i، حلقه داخلی (j) از 1 تا 5 می‌رود و حاصل ضرب i×j را چاپ می‌کند. بعد از اتمام حلقه داخلی، print() یک خط جدید ایجاد می‌کند تا سطر بعدی شروع شود.

✨ List Comprehension (لیست‌سازی فشرده)

راه سریع و زیبا برای ساخت لیست جدید از روی یک لیست یا دنباله دیگر. این روش بسیار پایتونیک (Pythonic) و خوانا است.

🐍 کد: مثال‌های List Comprehension
# ساخت لیست مربعات اعداد 1 تا 5
squares = [x**2 for x in range(1, 6)]
print("مربعات اعداد 1 تا 5:", squares)

# ساخت لیست فقط اعداد زوج از 1 تا 10
evens = [x for x in range(1, 11) if x % 2 == 0]
print("اعداد زوج:", evens)

# تبدیل حروف رشته به حروف بزرگ
letters = [char.upper() for char in "python"]
print("حروف بزرگ:", letters)
📝 توضیح: فرم کلی List Comprehension: [expression for item in iterable if condition]. در مثال اول، x**2 عبارت است، x متغیر حلقه، و range(1,6) iterable. در مثال دوم، شرط if x % 2 == 0 فقط اعداد زوج را انتخاب می‌کند. این روش بسیار سریع‌تر از ساختن لیست با حلقه for معمولی است.

🚀 پروژه‌های کاربردی

مثال ۱: بازی حدس عدد

🎮 کد: بازی حدس عدد با حلقه while
import random

print("به بازی حدس عدد خوش آمدید!")
print("من عددی بین 1 تا 100 انتخاب کرده‌ام. سعی کنید آن را حدس بزنید!")

secret_number = random.randint(1, 100)
attempts = 0
max_attempts = 7

while attempts < max_attempts:
    guess = int(input("حدس شما: "))
    attempts += 1
    
    if guess == secret_number:
        print(f"تبریک! شما برنده شدید! تلاش‌ها: {attempts}")
        break
    elif guess < secret_number:
        print("عدد بزرگ‌تری وارد کنید.")
    else:
        print("عدد کوچک‌تری وارد کنید.")
    
    print(f"تلاش‌های باقی‌مانده: {max_attempts - attempts}")
else:
    print(f"بازی تمام شد! عدد من {secret_number} بود.")
📝 توضیح: این بازی از حلقه while استفاده می‌کند زیرا تعداد دفعات دقیق حدس زدن از قبل مشخص نیست (حداکثر ۷ بار). تابع random.randint(1, 100) یک عدد تصادفی بین 1 تا 100 انتخاب می‌کند. با هر بار حدس، راهنمایی داده می‌شود و اگر عدد درست حدس زده شود، break اجرا می‌شود. بخش else بعد از حلقه زمانی اجرا می‌شود که حلقه بدون break به پایان برسد (یعنی کاربر نتواسته حدس بزند).

مثال ۲: چاپ الگو (مثلث ستاره‌ای)

🌟 کد: چاپ مثلث با حلقه تودرتو
rows = int(input("تعداد سطرها: "))

for i in range(1, rows + 1):
    # چاپ فاصله (برای وسط‌چین کردن)
    for j in range(rows - i):
        print(" ", end="")
    
    # چاپ ستاره
    for k in range(2 * i - 1):
        print("*", end="")
    
    # خط جدید بعد از هر سطر
    print()
📝 توضیح: این کد یک مثلث متقارن از ستاره چاپ می‌کند. حلقه اول تعداد سطرها را کنترل می‌کند. حلقه داخلی اول فاصله‌های ابتدای هر سطر را چاپ می‌کند (تعداد فاصله‌ها = rows - i). حلقه داخلی دوم ستاره‌ها را چاپ می‌کند که تعداد آن‌ها از فرمول 2*i - 1 به دست می‌آید (برای i=1: 1 ستاره، i=2: 3 ستاره، i=3: 5 ستاره و ...).

✍️ تمرینات عملی

🎯 تمرین ۱: جمع اعداد 1 تا 100
برنامه‌ای بنویسید که اعداد 1 تا 100 را جمع کند و نتیجه را نمایش دهد.
🔧 حل تمرین ۱:
# راه حل اول: با حلقه for
total = 0
for i in range(1, 101):
    total += i
print(f"جمع اعداد 1 تا 100: {total}")

# راه حل دوم: با فرمول ریاضی (سریع‌تر)
total_fast = 100 * 101 // 2
print(f"جمع با فرمول: {total_fast}")
📝 توضیح حل: در راه حل اول، متغیر total را صفر می‌گذاریم و در هر بار تکرار، مقدار i را به آن اضافه می‌کنیم. راه حل دوم از فرمول جمع اعداد طبیعی n*(n+1)/2 استفاده می‌کند که بسیار سریع‌تر است.
🎯 تمرین ۲: چاپ مربعات اعداد
برنامه‌ای بنویسید که مربعات اعداد 1 تا 10 را چاپ کند.
🔧 حل تمرین ۲:
print("مربعات اعداد 1 تا 10:")
for i in range(1, 11):
    print(f"{i} مربع = {i ** 2}")
📝 توضیح حل: از حلقه for با range(1, 11) استفاده می‌کنیم تا اعداد 1 تا 10 را پیمایش کنیم. عملگر ** برای محاسبه توان (i به توان 2) استفاده می‌شود.
🎯 تمرین ۳: پیدا کردن بزرگ‌ترین عدد
برنامه‌ای بنویسید که از کاربر 5 عدد بگیرد و بزرگ‌ترین آنها را نمایش دهد (بدون استفاده از تابع max()).
🔧 حل تمرین ۳:
largest = float('-inf')  # شروع با کوچک‌ترین عدد ممکن

for i in range(1, 6):
    num = float(input(f"عدد {i} را وارد کنید: "))
    if num > largest:
        largest = num

print(f"بزرگ‌ترین عدد: {largest}")
📝 توضیح حل: ابتدا largest را برابر منفی بی‌نهایت می‌گذاریم (تا هر عددی که وارد شود از آن بزرگتر باشد). سپس در هر بار تکرار، عدد جدید را با largest مقایسه می‌کنیم؛ اگر بزرگتر بود، largest را به‌روز می‌کنیم. در پایان، largest بزرگ‌ترین عدد خواهد بود.
🎯 تمرین ۴: شمارش حروف یک کلمه
برنامه‌ای بنویسید که یک کلمه از کاربر بگیرد و تعداد حروف آن را بشمارد (بدون استفاده از تابع len()).
🔧 حل تمرین ۴:
word = input("یک کلمه وارد کنید: ")
count = 0

for char in word:
    count += 1

print(f"تعداد حروف کلمه '{word}': {count}")
📝 توضیح حل: با حلقه for روی رشته، هر کاراکتر را یک بار پیمایش می‌کنیم و در هر بار تکرار، متغیر count را یک واحد افزایش می‌دهیم. در نهایت count برابر تعداد حروف خواهد بود.

📌 خلاصه و جمع‌بندی

  • حلقه for: برای تکرار روی یک دنباله (range، لیست، رشته) — زمانی که تعداد دفعات تکرار مشخص است.
  • حلقه while: تا زمانی که شرط درست است ادامه می‌دهد — باید شرط را تغییر دهیم تا حلقه بی‌نهایت نشود.
  • range(start, stop, step): تولید اعداد با شروع، پایان (قبل از stop) و گام مشخص.
  • break: خروج فوری از حلقه. continue: رد شدن از یک تکرار و رفتن به تکرار بعدی.
  • حلقه‌های تودرتو (Nested Loops): حلقه‌ای داخل حلقه دیگر — برای جداول، ماتریس‌ها و الگوها.
  • List Comprehension: روش فشرده و سریع برای ساخت لیست — [expression for item in iterable if condition]
🎯 نکته نهایی: حلقه‌ها قلب برنامه‌نویسی هستند. با تسلط بر حلقه‌ها، می‌توانید کارهای تکراری را به سادگی انجام دهید، داده‌های حجیم را پردازش کنید و برنامه‌های کارآمد و کوتاه بنویسید! انتخاب بین for و while به ماهیت مسئله بستگی دارد: اگر تعداد دفعات مشخص است → for، اگر شرط توقف مشخص است → while.
✅ کپی شد!