ویژگی تصویر

کتابخانه itertools در پایتون — راهنمای جامع و عملی

  /  پایتون   /  کتابخانه itertools در پایتون
بنر تبلیغاتی الف

کتابخانه itertools یک ماژول استاندارد در پایتون است که مجموعه‌ای از تولیدکننده‌های (iterators) کارا و بهینه برای کار با توالی‌ها فراهم می‌کند. این ماژول برای تولید ترکیبات، پردازش lazy روی داده‌های بزرگ و ساخت الگوهای مختلف پیمایشی بسیار مفید است. در این مقاله به صورت کاربردی و با مثال‌های واقعی به مهم‌ترین توابع، الگوهای رایج (recipes) و نکات بهینه‌سازی می‌پردازیم.

چرا از itertools استفاده کنیم؟

  • کارایی حافظه: اکثر توابع به‌صورت lazy عمل می‌کنند و داده‌ها را یک‌به‌یک تولید می‌کنند، بنابراین برای مجموعه‌های بزرگ مناسب‌اند.
  • خوانایی و اختصار: کدهایی که با itertools نوشته می‌شوند معمولاً کوتاه‌تر و قابل‌فهم‌ترند.
  • تنوع توابع: از تولید تمام جایگشت‌ها تا عملیات انباشته (accumulate) و گروه‌بندی پیشرفته را پوشش می‌دهد.

خلاصه‌ای از توابع مهم

تابعکاربرد
productدکارتی محصول (تولید تمام ترکیبات چند لیست)
permutationsتمام جایگشت‌ها
combinations / combinations_with_replacementترکیب بدون/با تکرار
chainوصل کردن چند iterator
isliceبرش lazy از iterator
teeتقسیم iterator به چند iterator مستقل
groupbyگروه‌بندی مرتب‌شده با کلید
accumulateمحاسبات تجمعی (مانند جمع تجمعی)

مثال‌های پایه

from itertools import permutations, combinations, product

items = ['a', 'b', 'c']
print(list(permutations(items, 2)))   # [('a','b'), ('a','c'), ('b','a'), ...]
print(list(combinations(items, 2)))   # [('a','b'), ('a','c'), ('b','c')]
print(list(product(items, repeat=2))) # دکارتی محصول: ('a','a'), ('a','b'), ...

در این کد، permutations تمام جایگشت‌های طول 2، combinations ترکیب‌های بدون ترتیب طول 2 و product تمام ترکیبات با تکرار طول 2 را تولید می‌کند. خروجی‌ها به‌صورت لیست نمایش داده شده‌اند اما توجه داشته باشید که ساختن لیست از iterator ممکن است حافظه زیادی مصرف کند؛ بهتر است روی آن‌ها به‌صورت lazy پردازش انجام دهید.

accumulate — محاسبات تجمعی

from itertools import accumulate
nums = [1, 2, 3, 4]
print(list(accumulate(nums)))  # [1, 3, 6, 10]

accumulate مجموع تجمعی عناصر را برمی‌گرداند. می‌توانیم تابع دلخواه مثل operator.mul برای ضرب تجمعی یا یک تابع سفارشی را نیز به آن بدهیم.

chain، islice و پردازش lazy

from itertools import chain, islice

a = range(1000000)
b = range(1000000, 2000000)
for x in islice(chain(a, b), 10):
    print(x)

chain دو iterator را به هم متصل می‌کند و islice به ما اجازه می‌دهد تنها تعداد معینی از نتایج را مصرف کنیم؛ این ترکیب برای خواندن بخشی از داده‌های عظیم بسیار کارا است چون از بارگذاری همه داده‌ها در حافظه جلوگیری می‌کند.

groupby — گروه‌بندی مرتب‌شده

from itertools import groupby
data = [('apple', 2), ('apple', 3), ('banana', 1), ('banana', 4)]
for key, group in groupby(sorted(data, key=lambda x: x[0]), key=lambda x: x[0]):
    print(key, list(group))

groupby گروه‌ها را بر اساس کلیدی که شما تعیین می‌کنید گروه‌بندی می‌کند، اما توجه کنید که ورودی باید ابتدا بر اساس همان کلید مرتب شده باشد؛ در غیر این صورت گروه‌ها به‌درستی شکل نمی‌گیرند.

الگوهای رایج (recipes)

در مستندات itertools مجموعه‌ای از الگوهای مفید وجود دارد. برخی کاربردی که اغلب به‌کار می‌آیند:

  • pairwise — تولید pasangan (a, b) برای پیمایش‌های مجاور
  • grouper — تقسیم به بلوک‌های ثابت طول
  • sliding window — پنجره متحرک روی یک دنباله
from itertools import tee, islice

def pairwise(iterable):
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

print(list(pairwise([1,2,3,4])))  # [(1,2), (2,3), (3,4)]

در این نسخه از pairwise از tee برای کپی کردن iterator استفاده شده و سپس با جلو انداختن یکی از کپی‌ها، جفت‌های مجاور ساخته می‌شوند. اشاره: tee می‌تواند حافظه بیشتری مصرف کند اگر بین iteratorها با تاخیر مصرف شود.

نمونه پیشرفته — sliding window بهینه

from collections import deque
from itertools import islice

def sliding_window(iterable, n):
    it = iter(iterable)
    window = deque(islice(it, n), maxlen=n)
    if len(window) == n:
        yield tuple(window)
    for x in it:
        window.append(x)
        yield tuple(window)

این پیاده‌سازی از deque با حداکثر طول n استفاده می‌کند که برای پنجره متحرک بسیار کارا است و از بازتولید لیست‌ها جلوگیری می‌کند. ابتدا n عنصر اولیه را می‌خوانیم و سپس با هر عنصر جدید پنجره را به‌روزرسانی می‌کنیم.

نکات عملکردی و بهترین شیوه‌ها

  • از iteratorها استفاده کنید تا از حافظهٔ زیاد جلوگیری شود؛ فقط زمانی لیست بسازید که واقعاً نیاز دارید.
  • در عملیات ترکیبی بزرگ مانند تولید تمام جایگشت‌ها یا همهٔ ترکیبات، هشدار حافظه و زمان اجرا را در نظر بگیرید؛ گاهی نیاز به محدود کردن با islice یا فیلتر هست.
  • در مواقع نیاز به چند خواندن از یک iterator، از tee استفاده کنید اما مراقب حافظه باشید—tee یک بافر داخلی نگه می‌دارد.
  • برای عملیات گروه‌بندی، همیشه داده‌ها را ابتدا بر اساس همان کلید مرتب کنید تا groupby نتایج منطقی دهد.

موارد استفاده واقعی

  • علوم داده: پردازش دسته‌ای فایل‌های بزرگ یا تولید پنجره‌های زمانی در سری‌های زمانی.
  • تست و تولید سناریوها: تولید تمام ترکیبات پارامترها برای تست پوششی.
  • پردازش متنی: نرمال‌سازی و گروه‌بندی توکن‌ها، یا ایجاد n-gramها با sliding window.

مثال بهینه‌سازی — محدود کردن تولید ترکیبات

from itertools import combinations, islice

# تولید اولین 100 ترکیب بدون ساخت کل لیست
items = range(100)
first_100 = list(islice(combinations(items, 5), 100))

در این مثال به‌جای ایجاد همهٔ ترکیبات C(100,5) که بسیار بزرگ است، با islice تنها 100 مورد اول را می‌گیریم؛ این کار از مصرف زیاد حافظه جلوگیری می‌کند.

جمع‌بندی

کتابخانه itertools یک مجموعه قدرتمند و بهینه برای کار با iteratorها و تولید الگوهای پیمایشی است. یادگیری توابع پایه مانند product، permutations، combinations، chain، islice، groupby و استفاده از recipes می‌تواند کدهای شما را هم خواناتر و هم سریع‌تر کند. همیشه به امکانات lazy و محدودیت‌های حافظه توجه داشته باشید و در کاربردهای واقعی با نمونه‌های کوچک آزمایش کنید تا بهترین الگو را بیابید.

آیا این مطلب برای شما مفید بود ؟

خیر
بله
موضوعات شما در انجمن: