فصل ۳: کنترل جریان — تصمیم‌گیری و تکرار

enumerate، zip، any/all و الگوریتم‌های کوچک

حلقه‌ی پایتونیک

کسانی که از زبان‌های دیگر می‌آیند معمولاً می‌نویسند for i in range(len(names)): و بعد names[i]. در پایتون تقریباً هیچ‌وقت به این نیاز ندارید؛ ابزارهای بهتری هست.

enumerate: شماره و عضو با هم

customers = ["رضا احمدی", "مریم کاشانی", "سارا نراقی"]

for i, name in enumerate(customers, start=1):
    print(f"{i}. {name}")

enumerate در هر دور یک جفت (شماره، عضو) تحویل می‌دهد و با start=1 شماره‌گذاری برای انسان‌ها طبیعی‌تر می‌شود.

zip: پیمایش موازی

وقتی چند لیست هم‌طول دارید که عضوهای متناظرشان به هم مربوط‌اند، zip آن‌ها را جفت می‌کند:

names = ["رضا", "مریم", "سارا"]
sizes = [6, 12, 9]          # متر مربع
prices = [7_800_000, 9_500_000, 8_200_000]   # ریال برای هر متر

for name, size, price in zip(names, sizes, prices, strict=True):
    print(f"{name}: {size * price:,} ریال")

zip به‌طور پیش‌فرض با رسیدن به انتهای کوتاه‌ترین لیست بی‌صدا متوقف می‌شود؛ اگر یکی از لیست‌ها به‌اشتباه کوتاه‌تر باشد، داده گم می‌شود و هیچ خطایی نمی‌بینید. آرگومان strict=True (از 3.10) در این حالت ValueError می‌دهد؛ عادت کنید آن را بنویسید.

any و all

if any(s > 10 for s in sizes):
    print("دست‌کم یک فرش بزرگ داریم")
if all(p > 0 for p in prices):
    print("همه‌ی قیمت‌ها معتبرند")

الگوریتم‌های کوچک، دست‌ساز

پایتون برای بیشتر کارها تابع آماده دارد (sum، max، min، sorted)، اما یک‌بار دستی نوشتنشان منطق حلقه را در ذهن می‌نشاند:

def biggest(values):
    best = values[0]
    for v in values[1:]:
        if v > best:
            best = v
    return best

def knots_per_sqm(raj: int) -> int:
    # «رج» تعداد گره در ۷ سانتی‌متر است؛ تراکم در یک متر مربع
    per_meter = raj * 100 / 7
    return round(per_meter ** 2)

print(biggest([12, 6, 30, 9]))        # 30
print(f"{knots_per_sqm(50):,}")        # 510,204 گره در متر مربع

و با ابزار آماده: max(sizes)، sum(prices) / len(prices) برای میانگین، و max(names, key=len) برای طولانی‌ترین نام. پارامتر key را در فصل بعد عمیق‌تر می‌بینیم.

تمرین پیشنهادی

  1. برنامه‌ای بنویسید که تا کاربر «پایان» نزده، قیمت بگیرد و در پایان تعداد، جمع، میانگین، بیشینه و کمینه را چاپ کند.
  2. فهرستی از کدهای سفارش بگیرید و کدهای تکراری را با یک حلقه و یک لیست کمکی پیدا کنید.
  3. جدول ضرب ۱ تا ۹ را با دو حلقه‌ی تودرتو و f-string تراز شده چاپ کنید.

نکته‌هایی که کمتر کسی می‌داند

  • zip(*rows) جدول را ترانهاده می‌کند: سطرها ستون می‌شوند. list(zip(*[[1, 2, 3], [4, 5, 6]])) می‌دهد [(1, 4), (2, 5), (3, 6)].
  • any و all میان‌بری هستند: any با اولین True و all با اولین False متوقف می‌شود. all([]) برابر True است (هیچ مثال نقضی نیست!).
  • max و min روی لیست خالی خطا می‌دهند؛ پارامتر default نجاتتان می‌دهد: max(prices, default=0).
  • zip و enumerate خودشان «تکرارکننده» (iterator) هستند و یک‌بار مصرف‌اند؛ اگر نتیجه را دو بار لازم دارید، با list() ذخیره کنید.
  • برای جفت‌های پشت‌سرهم (مثلاً اختلاف قیمت روزها) از itertools.pairwise(prices) استفاده کنید، نه اندیس‌بازی.

برای ذخیره‌ی پیشرفت و شرکت در آزمون، وارد شوید — رایگان است.