تابع Generator یا مولد در پایتون

تابع Generator یا مولد در پایتون

تابع Generator یا مولد


داخل این مقاله قراره با هم راجع به تابع مولد یا Generator در پایتون صحبت کنیم تابعی هستش که میتونه متوقف بشه و بعد به حالت عادی خودش برگرده . این تابع یک شیء از مقادیر قابل پیمایش میتونه برگردونه. به عبارت دیگه ای میشه گفت که Generator، یک نوع قابل شمارش، مثل لیست هایی هستش که مجموعه ای از مقادیر قابل شمارش را در اختیار ما قرار میدن. برای ایجاد یک Generator کافیه که یک تابع عادی تعریف کنیم و فقط به جای دستور return از دستور yield استفاده کنیم :


  : ()def myGenerator


Code to execute #


yield something


یکی از تفاوت هایی که یک تابع عادی با یک Generator داره اینه که تابع عادی فقط میتونه یک دستور return داشته باشه و در نتیجه یک مقدار را بیشتررو نمیتونه برگشت بده ولی یک Generator میتونه دارای چند دستور yield و در نتیجه چند خروجی داشته باشه. تفاوت دیگه Generator با یک تابع عادی این هستش که وقتی ما یک تابع عادی را صدا می زنیم، کدها از ابتدا تا انتها اجرا میشن ولی Generator حالت قبلی خودش رو  ذخیره و در فراخوانی های بعدی از ا.ن حالت به بعد را اجرا می کنه.
چون Generator یک نوع قابل پیمایش بر می گردونه در نتیجه میشه گفت از حلقه ها برای به دست آوردن مقادیرش میشه استفاده کرد. به مثال زیر توجه کنین :


   : () def counter


i=1    


  : while(i<=10)    


yield i    


i+=1    


print(counter())


خروجی برنامه :


<generator object counter at 0x00517B70>


در کد بالا، یک تابع با نام ()counter ایجاد کردیم و در داخل یک حلقه برای برگردوندن مقادیر 10-1 نوشتیم. این مقادیر رو به جای دستور return با دستور yield برگشت میدیم. همونطور که مشاهده می کنید، با چاپ تابع ()counter نوع آن در خروجی نمایش داده می شه که در اصل همون Generator هستش.حالا چون این تابع از نوع Generator هست می تونیم مقادیر داخل اون رو با استفاده از حلقه for به صورت زیر چاپش کنیم:


 : () def counter


i=1    


  : while(i<=10)    


yield i    


i+=1    


 : () for i in counter


 (i)print      


خروجی برنامه :


1


2


3


4


5


6


7


8


9


10


 


همونطور که گفته شد در کد بالا یک Generator داریم که اعداد 10-1 تا تولید می کنه و در داخل حلقه while هر با مقدار i را یک واحد اضافه میکنه و این کار را تا عدد 10 ادامه می دیم. یعنی هر بار مقدار i یک واحد بیشتر از مقدار قبلی می شه. بعد مقادیر تولید شده توسط Generator را به حلقه for می دیم تا چاپ بشن. وجود دستور yield باعث می شه که با هر درخواست، تابع از اول اجرا نشه. یعنی وضعیت رو تشخیص میده. با این وضع  خطوط 3-1 یک بار اجرا میشن.


وقتی که اولین بار در خط 7، حلقه اجرا میشه، خطوط 5-1 اجرا میشه و مقدار 1 تولید و در خط 8 چاپ میشن. وقتی که برای بار دوم حلقه اجرا بشه، دیگه خطوط 3-1 اجرا نمیشن بلکه برنامه به خط 4 میره و اون رو اجرا می کنه. این به این معنی هستش که دستور yield وضعیت برنامه را ذخیره کرده و میدونه که در درخواست بعد باید آیتم بعدی Generator را برگردونه. این کار باعث صرفه جویی در حافظه میشه.


همونطور که گفته شد، Generator ها یک شیء قابل پیمایش بر می گردونن، در نتیجه میشه گفت با استفاده از تابع ()next به تک تک آیتم های این شیء میشه دسترسی پیدا کرد. به کد زیر توجه کنین:


  : def myGenerator(number)


yield number    


    yield number + 1   


generator = myGenerator(6)


print(next(generator))


print(next(generator))


خروجی برنامه :


6


7


در فراخوانی اول تابع ()next در خط 7، ابتدا خطوط 1 و 2 اجرا میشن و در فراخوانی دوم تابع ()next برنامه خط 3 را اجرا میکنه. همونطور که در کد بالا احتمالا متوجه شدید یک Generator میتونه دارای چندین دستور yield باشه. اگه بعد از خط 9 یک بار دیگه دستور print(next(generator)) رو بنویسیم، با خطای StopIteration مواجه می شویم. به جای خطوط 8-7 میشه از دستور for هم به صورت زیر استفاده کرد:


 : for n in myGenerator(6)


print(n)


به این معنی هستش که حلقه for در پس زمینه، تابع ()next را فراخوانی میکنه.

نویسنده بلاگ: جواد یوسفی

جواد یوسفی

برنامه نویس فرانت اند

دیدگاه کاربران

    هیچ نظری ثبت نشده! اولین نفری باش که نظرشو ثبت میکنه!

ثبت دیدگاه

برای ثبت نظر، ابتدا وارد شوید.

خدمات منتورینگ

شما در طول دوره ی آنلاین میتوانید یک پشتیبان یا همراه داشته باشید و تمامی تمرین ها و مشکلات خودتون رو با اپراتور های ما در میان میگذارید! چی بهتر از اینکه قدم به قدم در کنار اساتید و آموزش های آنلاین بتونی از طریق پشتیبان هم ارزیابی بشی و مشکلاتت رو توی کمترین زمان ممکن حل کنی؟!!