همون طوری که میدونی list ها مجموعه ای از مقادیر هستن که توی حافظه نگهداری میشن. حالا فرض کن به جای نگهداری مجموعه ای از مقادیر مشخص، فرمول درست کردن شون رو نگه داری کنیم و هر وقت که یکی شون رو لازم داشتیم محاسبه کنیم. این جاست که بحث Generator ها میاد وسط. بذار با مثال پیش بریم.
فرض کن میخایم list ای از اعداد رو به یک تابع بدیم و مربع شون رو بگیریم:
def squares(nums): results = [] for num in nums: results.append(num * num) return results
حاصل تابع بالا، جدا از این که هر لیستی با هر اندازه ای بهش بدیم، در هر صورت یک list خواهد بود که تک تک عناصرش عینا محاسبه میشه و در نهایت کل حاصل return میشه. حالا اگه بخایم همین تابع رو با فلسفه generator ها بزنیم:
def squares(nums): for num in nums: yield num * num
این جا دیگه نه return داریم و نه results بلکه هر دفعه باید از تابع next استفاده کنیم تا مقدار اون چرخه رو حساب کنیم. این طوری:
results = squares([1,2,3,4,5]) print(next(results)) # 1 print(next(results)) # 4 print(next(results)) # 5
میشه بدون نیاز به تعریف یک function و به صورت مستقیم با استفاده از comprehension یک generator درست کرد. این طوری:
my_generator = (x*x for x in range(1,6)) print(next(my_generator)) # 1 print(next(my_generator)) # 4 print(next(my_generator)) # 9
در این حالت دیگه نیازی به تابع و کلیدواژه yield نیست.
نکات
برای تبدیل یک generator به یک لیست واقعی کافیه به تابع list بدیمش. مثل بقیه تبدیل ها!
real_list = list(my_generator)
اگر بیش از اندازه قابل تصور generator از تابع next استفاده کنیم حاصلی وجود نخواهد داشت که تابع next بخاد به ما برگردونه برای همین exception رخ میده. برای همین توصیه میشه از تابع next با احتیاط استفاده کنید یا این که توی بلوک try قرارش بدیم.
تو پروژه های کوچیک اهمیت بین list واقعی و generator حس نمیشه ولی وقتی که حجم data مورد پردازش عظیم میشه (که تو دنیای واقعی اتفاقا این طوریه) تسلط به همین ویژگی های زبان پایتان هست که بین یک برنامه نویس Junior و Senior تفاوت ایجاد میکنه. خیلی وقت ها شنیدیم که میگن مثلا PHP در برابر Node اصلا سرعتی نداره. در یک دید کلی این درسته ولی یک برنامه نویس حرفه ای با تسلط به مباحثی مثل همین generator ها ممکنه کدی رو با PHP بنویسه که خیلی سریع باشه (generator ها مختص زبان پایتان نیستن). پس سعی کن که generator ها رو یاد بگیری.