سطح مقدماتی (Beginner Level)
در پایتون، نوشتن حلقهها قواعد خاص خود را دارد. بسیاری از برنامهنویسانی که از زبانهای دیگر (مثل C یا Java) میآیند، برای دسترسی به «اینکس» (Index) و «مقدار» (Value) به صورت همزمان، کدهای پیچیدهای مینویسند. توابع داخلی enumerate و zip ابزارهایی هستند که کدهای ما را تمیزتر و خواناتر میکنند.
۱. تابع Enumerate (شمارشگر)
فرض کنید یک لیست از اسامی دارید و میخواهید آنها را همراه با شماره ردیف چاپ کنید. روش قدیمی استفاده از range(len(list)) است، اما روش پایتونیک استفاده از enumerate است.
همچنین میتوانید تعیین کنید شمارش از چه عددی شروع شود (مثلاً از ۱ به جای ۰):
۲. تابع Zip (ترکیب لیستها)
اگر دو لیست جداگانه داشته باشید (مثلاً یکی نام دانشآموزان و دیگری نمرات آنها) و بخواهید همزمان روی هر دو حلقه بزنید، از zip استفاده میکنیم. این تابع مانند یک زیپ واقعی، آیتمهای اول را با هم، آیتمهای دوم را با هم و... جفت میکند.
# Static Code: Concept of Zip result
# zip returns an iterator of tuples
# list(zip(['a', 'b'], [1, 2])) -> [('a', 1), ('b', 2)]
سطح پیشرفته (Professional Level)
در این بخش به نکات عمیقتر، مدیریت لیستهای نامتوازن و ترفندهای حافظه میپردازیم.
۱. مشکل لیستهای نامساوی و zip_longest
تابع استاندارد zip به محض تمام شدن کوتاهترین لیست، متوقف میشود. این یعنی اگر یک لیست طولانیتر باشد، دادههای انتهایی آن از دست میروند (Truncation). برای حل این مشکل از ماژول itertools استفاده میکنیم.
۲. آنزیپ کردن (Unzipping)
یک تکنیک حرفهای استفاده از عملگر * برای معکوس کردن عملیات zip است. این کار زمانی مفید است که یک لیست از تاپلها دارید و میخواهید آنها را به دو لیست مجزا تبدیل کنید.
۳. ساخت دیکشنری با Zip
یکی از سریعترین و تمیزترین روشها برای ساخت یک دیکشنری از دو لیست (یکی کلید و دیگری مقدار)، استفاده از ترکیب dict و zip است.
نکات عملکردی (Performance)
توابع zip و enumerate در پایتون ۳ به صورت Lazy Iterator عمل میکنند. یعنی تمام لیست جدید را در حافظه بارگذاری نمیکنند، بلکه در هر لحظه فقط عنصر مورد نیاز را تولید میکنند. این ویژگی باعث میشود برای کار با کلاندادهها (Big Data) بسیار بهینه باشند.
# Static Code: Memory Efficiency
# This creates a generator, not a huge list in memory
large_range = range(1000000)
zipped = zip(large_range, large_range)
# Consumes memory only when iterated
# next(zipped)