حلقهی پایتونیک
کسانی که از زبانهای دیگر میآیند معمولاً مینویسند 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 را در فصل بعد عمیقتر میبینیم.
تمرین پیشنهادی
- برنامهای بنویسید که تا کاربر «پایان» نزده، قیمت بگیرد و در پایان تعداد، جمع، میانگین، بیشینه و کمینه را چاپ کند.
- فهرستی از کدهای سفارش بگیرید و کدهای تکراری را با یک حلقه و یک لیست کمکی پیدا کنید.
- جدول ضرب ۱ تا ۹ را با دو حلقهی تودرتو و 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)استفاده کنید، نه اندیسبازی.