Arsham Roshannejad
Arsham Roshannejad
خواندن ۵ دقیقه·۲ سال پیش

جنریتور ها در پایتون

در پایتون، جنریتور یک تایپ خاص از iterable است، شبیه به یک لیست یا یک تاپل، اما با چند تفاوت کلیدی. برخلاف لیست ها یا تاپل ها، جنریتورها محتویات خود را در رم ذخیره نمی کنند. درعوض، آن‌ها مقدار ها را همان‌طور که درخواست می شود، تولید می‌کنند.

جنریتور تایپی iterable است که به جای اینکه همه مقادیر را به یکباره در رم ذخیره کند، دنباله ای از مقادیر را تولید می کند. این می تواند برای کار با توالی های بزرگ یا نامتناهی از داده ها مفید باشد، زیرا به شما امکان می دهد به جای اینکه سعی کنید همه چیز را همزمان در رم بارگذاری کنید، با یک مقدار در یک زمان کار کنید.

جنریتورها هنگام برخورد با مجموعه داده های بزرگ یا توالی های نامحدود مفید هستند، جایی که تولید همه مقادیر به یکباره و ذخیره آنها در رم غیرعملی یا غیرممکن است. جنریتورها با تولید مقادیری که در لحظه نیاز دارند، به ما این امکان را می‌دهند که با این مجموعه داده‌ها به طور موثر و بدون تمام شدن حافظه کار کنیم.


دلایل مختلفی وجود دارد که ممکن است بخواهید از یک جنریتور در پایتون استفاده کنید:

  • کارایی حافظه: جنریتورها به شما امکان می‌دهند توالی‌های بزرگ یا نامتناهی از داده‌ها را تولید و پردازش کنید بدون اینکه مجبور باشید همه چیز را به یکباره در رم بارگذاری کنید. این می تواند در هنگام کار با مجموعه داده های بسیار بزرگ یا هنگام کار با جریان های داده ای که بیش از حد بزرگ هستند که در رم جای نمی گیرند مفید باشد.
  • ارزیابی تنبل :| (Lazy evaluation): جنریتورها به جای اینکه همه داده ها را به یکباره تولید کنند، داده ها را همان طور که درخواست می شود، در لحظه ارزیابی می کنند. این می تواند زمانی مفید باشد که فقط نیاز به دسترسی به بخشی از مجموعه داده بزرگتر دارید، یا زمانی که نمی خواهید زمان خود را صرف تولید داده هایی کنید که ممکن است در نهایت از آنها استفاده نکنید.
  • ساده کردن کد: جنریتورها می توانند کد را با اجازه دادن به شما برای بیان عملیات پیچیده به عنوان دنباله ای از توابع ساده جنریتور، به جای ایجاد و مدیریت ساختارهای داده پیچیده تر، ساده کنند.
  • عملکرد بهبود یافته: از آنجایی که جنریتورها به شما اجازه می دهند تا عملیات روی داده ها را در حین تولید انجام دهید، اغلب می توانند منجر به بهبود عملکرد و کاهش مصرف رم در مقایسه با تکنیک های برنامه نویسی سنتی شوند.
  • قابلیت همکاری: جنریتورها تکرارپذیر هستند، که کار آنها را در زمینه های مختلف، از جمله حلقه ها، list comprehensions و سایر عملیات های مبتنی بر تکرار آسان می کند.

به طور کلی، جنریتورها می‌توانند ابزار قدرتمندی برای کار با توالی‌های بزرگ، پیچیده یا نامتناهی از داده‌ها به روشی انعطاف‌پذیر، کارآمد و سازگار با رم باشند.


مثال:

در این کد یک تابع جنریتور به نام ()fibonacci تعریف شده است که دنباله فیبوناچی را به طور نامحدود تولید می کند. کلمه کلیدی yield برای به دست آوردن هر مقدار در دنباله ای که تولید می شود استفاده می شود.

سپس تابع جنریتور فراخوانی شده و به متغیر gen نسبت داده می شود. یک آبجکت جنریتور ایجاد می کند که می تواند برای تولید دنباله فیبوناچی استفاده شود.

در نهایت تابع print() با آرگومان آبجکت gen فراخوانی می شود. با این حال، این عملا دنباله فیبوناچی را چاپ نمی کند. در عوض، نمایش رشته‌ای از آبجکت جنریتور را چاپ می‌کند، که چیزی شبیه <generator object fibonacci at 0x7ff6137ea5e0> خواهد بود.


برای تولید دنباله فیبوناچی، می‌توانید از آبجکت جنریتور برای تکرار روی دنباله استفاده کنید و هر مقدار را در لحظه تولید کنید، برای مثال:

این کد 10 عدد اول را در دنباله فیبوناچی ایجاد می کند: 0، 1، 1، 2، 3، 5، 8، 13، 21، 34.

توجه داشته باشید که تابع next() برای بازیابی مقدار بعدی در دنباله هر بار از طریق حلقه استفاده می شود.

روش بعدی:

شش فراخوانی ()next در این کد وجود دارد، بنابراین شش عدد اول در دنباله فیبوناچی تولید و در ترمینال چاپ خواهند شد.

آبجکت جنریتور gen وضعیت فعلی تابع فیبوناچی را ردیابی می کند، بنابراین هر فراخوانی بعدی از جایی که تماس قبلی متوقف شده است ادامه می یابد.

از طرف دیگر، می‌توانید از تابع itertools.islice() برای بدست آوردن slice ای از دنباله استفاده کنید:

  • تابع islice دو آرگومان می گیرد: آبجکت جنریتور برای slice، و تعداد آیتم هایی که باید در slice گنجانده شود. در این مورد، slice شامل 10 مورد اول در دنباله است.
  • تابع list() برای تبدیل آبجکت slice به لیست استفاده می شود تا بتوان آن را چاپ کرد.
  • هنگامی که این کد اجرا می شود، خروجی لیستی از 10 عدد اول در دنباله فیبوناچی خواهد بود: [0، 1، 1، 2، 3، 5، 8، 13، 21، 34].

استفاده از itertools.islice() یک راه راحت برای بدست آوردن slice ای از یک آبجکت جنریتور بی نهایت بدون نیاز به تولید کل دنباله است. تنها با تولید آیتم های مورد نیاز خود، می توانید در رم و زمان پردازش صرفه جویی کنید، به خصوص هنگام کار با توالی های بزرگ یا بی نهایت.


تابع جنریتور دنباله فیبوناچی را به طور نامحدود تولید می کند. هر بار که جنریتور فراخوانی می شود، مقدار بعدی را در دنباله تولید می کند.

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


پایتونتولیدبرنامه نویسی
سافتویر اینجینیر
شاید از این پست‌ها خوشتان بیاید