Skip to main content

পাইথনে জেনারেটর ও তার খুঁটিনাটি বিষয়

এখানে আমরা দেখব যে পাইথনে জেনারেটর বিষয়টা কি । আমরা কিভাবে জেনারেটর বানাতে পারি । জেনারেটর এক্সপ্রেশন কি ? আমাদের কেন ও কি অবস্থায় জেনারেটর ব্যবহার করা দরকার । তো শুরু করা যাক ।

জেনারেটর কি ?

পাইথনে iterator তৈরি করার সবচেয়ে সহজ উপয় হল জেনারেটর । সাধারণ ভাবে বলতে গেলে জেনারেটর একটা ফাংশন যেটা একটা iterator অবজেক্ট রিটার্ন করে । যেটাকে পরে আমরা iterate করতে পারি । এবং যেটা কেবল মাত্র একবারই iterate করা যাবে ।

এখন প্রশ্ন হল এই জেনারেটর কিভাবে বানানো যায় ?

জেনারেটর বানানো খুব সহজ । আমরা সাধারণ ফাংশন যেভাবে লিখি ঠিক সেভাবেই আমরা জেনারেটর বানাতে পারি । কিন্তু এখানে return স্টেটমেন্টের পরিবর্তে yield স্টেটমেন্ট থাকবে । যদি কোন একটা ফাংশনে অন্তত একটা yield স্টেটমেন্ট থাকে তবে সেটা কে আমরা জেনারেটর বলতে পারি । তবে একটা জেনারেটরে একাধিক yield স্টেটমেন্ট থাকতে পারে ।

yield এবং return দুইটাই ফাংশন থেকে কোন ভেলু রিটার্ন করে কিন্তু দুইটার মধ্যে পার্থক্য হল return স্টেটমেন্ট একটা ফাংশন কে পুরাপুরি terminate করে ফেলে । কিন্তু yield ফাংশন কে terminate না করে ফাংশনকে pauses করে রাখে + ফাংশনের বর্তমান অবস্থাও সেভ করে রাখে এবং পরবর্তীতে ফাংশনের আগের অবস্থা থেকেই কাজ শুরু করে ।

কি জটিল মনে হচ্ছে ? একটা কোড দেখি তাহলে বিষয়টা সহজ হয়ে যাবে । মনে করি আমাদের my_generator() নামে একটা ফাংশন আছে যেটার মধ্যে একাধিক yield স্টেটমেন্ট আছে ।
next(a) কল করার পরে দেখা যাচ্ছে যে আমাদের পুরা ফাংশন কিন্তু কল হয় নি । 6 নং লাইনে এসে থেমে আছে । 6 নং লাইনের আগেই কাজ কিন্তু সে ঠিকই করে ফেলছে । এখন আমরা যদি আবার next(a) দিয়ে কল করি তবে কি ঘটনা ঘটে দেখি ।
এখানে দেখা যাচ্ছে জা ৮ নং লাইন থেকে ১০ নং লাইন পর্যন্ত কাজ হয়েছে । এবং n পরিবর্তিত মান কে সে মনে রেখেছে । ফলে n = 1 এর সাথে 1 যোগ করে নতুন মান ২ রিটার্ন করেছে । এখন আমরা যদি আবার next(a) কল করি তবে সে একই কাজ করবে ।
সে কিন্তু n = 2 এর সাথে ১ যোগ করে ৩ রিটার্ন করেছে । আচ্ছা এখন আমরা যদি আবার next(a) কে কল করি তবে কি ঘটনা ঘটবে ? দেখা যাক রান করে দেখি কি ঘটে ।
Traceback এ দেখে যাচ্ছে যে StopIteration নামে একটা exception খাইছে । এর কারণ আমারা যে generator বানিয়েছি সেটা তো ৩ টা জিনিসই রিটার্ন করে । তো সেখান থেকে আমি কখনই ৪ টা জিনিস আশা করতে পারি না ।
উপরের ঘটনাগুলির সারাংশ এইরকম হতে পারে
  1. প্রত্যেক কল এ ভেরিয়েবল n এর মান মনে রাখা হয় ।
  2. সাধারণ ফাংশনের মত ভেলু রিটার্ন করার পরে লোকাল ভেরিয়েবল ধ্বংস হয়ে যায় না ।
  3. Generator অবজেক্ট কেবল একবারই iterate করা যায়
  4.  নতুন করে iterate করা জন্য আমাদের কে a = my_generator() আবার কল করতে হবে ।

Python Generators কে লুপের মাধ্যমে iterate করা :


Python Generator Expression:

এটা হল ফাংশন ক্রিয়েট না করেই জেনারেটর অবজেক্ট ক্রিয়েট করা । আমাদের জেনারেটর ফাংশন যদি খুব ছোট হয় তবে সেটা ইমপ্লিমেন্ট করা জন্য আলাদা করে ফাংশন ডিফাইন করার দরকার নাই । ল্যামডা ফাংশন যেমন anonymous function ক্রিয়েট করতে পারে । ঠিক তেমনি ভাবে generator expression, anonymous generator ফাংশন ক্রিয়েট করতে পারে ।

Generator expression এর সিনট্যাক্স list comprehension এর মতই শুধু পার্থক্য হল এখানে square brackts এর পরিবর্তে round parentheses ব্যবহার করা হয় । কিছু উদাহরণ দেখা যাক ।

কেন আমরা Generator ব্যবহার করব ?

অনেকের মনে হতে পারে যে জেনারেটরের কাজ তো সাধারণ ফাংশন ও লিস্ট কম্প্রিহেন্সনের মাধ্যমেই করা যায় তবে এটা দরকার টা কি ? এর বেশ কিছু সুবিধা আছে তার মধ্যে অন্যতম

মেমরি খরচ অনেক কমায়ে দেয় :

প্রশ্ন হতে পারে যে মেমরি খরচ কিভাবে কমায়ে দেয় ? মনে করেন আমাদের একটা ফাংশন আছে যেটা 2GB ইমেজ ফাইল রিড করে একটা লিস্ট ভেরিয়েবলে স্টোর করে রাখে সব ফাইল রিড করা শেষ হলে লিস্ট টি রিটার্ন করে দেয় । আমাদের ফাংশন টা যদি সাধারণ ফাংশন হয় তবে এটা পুরা 2GB ইমেজের ডাটা কে মেমরিতে তে লোড করে রাখবে যতক্ষণ না সেটা ফাইনাল লিস্ট কে return করে ।

কিন্তু আমরা যদি জেনারেটর ব্যবহার করি তবে আমাদের কে পুরা 2GB ইমাজের ডাটা কে মেমরিতে লোড করতে হচ্ছে না । কারণ আমরা দেখেছি যে জেনারেটর একক সময়ে কেবল একটাই আইটেম রিটার্ন করে ।

অসীম একটা Stream কে রিপ্রেজেন্ট করা যায়:

আপনার যদি অসীম সংখ্যক ডাটা থাকে তবে আপনি খুব সহজেই জেনারেটর দিয়ে সেটা কে রিপ্রেজেন্ট করতে পারবেন । কি বিশ্বাস হচ্ছে না ? আমরও অবশ্য শুরুতে বিশ্বাস হয় নি । কিন্তু এখন হয় । একটা উদাহরণ দেই তাহলেই বিশ্বাস হয়ে যাবে ।

Fibonacci numbers এর সাথে আমরা অনেকেই পরিচিত । তো আমরা Fibonacci number এর অসীম stream generate করার চেষ্টা করি ।
বিশাল বড় দুইটা Fibonacci সংখ্যা দিয়ে দিছে । কি ভয়ঙ্কর সুন্দর ও সাঙ্ঘাতিক ব্যাপার । আপনার মেশিন যতটুকু লোড নিতে পারবে সেটা উপর ভিত্তি করে আপনি 10000, 10002 এইটা দুইটা মান ছোট ও বড় বসাতে পারেন । আমার মেশিনে এর থেকে বড় সংখ্যা দিলে মেশিনের অবস্থা খারাপ হয়ে যাবে ।

আপনার সিস্টেম সবচেয়ে বড় কি সংখ্যা দেয়া যেতে পারে তার জন্য আপনই sys.maxsize দিয়ে সাইজ দেখে নিতে পারেন ।

এই দুইটা বাদেও generator এর আরও কিছু আপ্লিকেশন আছে । সেগুলো জানার জন্য আপনি গুগল করতে পারেন । আজকে এ পর্যন্তই ।

মুল লেখা: https://github.com/menon92/Python-Learning/blob/master/python_generator_by_example.ipynb

Comments

Popular posts from this blog

উইন্ডোজ এর Diskpart এর কিছু কমান্ড নিয়ে কাজ করা

অনেক সময় দেখা যায় যে উইন্ডোজ দেয়ার সময় আমরা আমাদের হার্ডডিস্ক কে গুই ব্যবহার করে আমাদের প্রয়োজন অনুসারে ভাগ করতে পারি না । সেই ক্ষেত্রে আমারা যদি ডিস্কপার্ট সফটওয়্যার টি ব্যাবহার করি তবে সহজেই সেটা করতে পারব ।  উইন্ডোজ দেয়ার সময় যখন Install Windows অপশন আসে তখন আমারা যদি Shift + F10 চাপি তবে উইন্ডোজ এর কমান্ড লাইন চলে আসবে । সেখানে যদি আমরা diskpart লিখলেই diskpart ওপেন হবে । এখানে আমরা ডিস্কপার্ট এর বিভিন্ন কমান্ড ব্যাবহার করতে পারব ।     এখন দেখব ডিস্কপার্ট এর বিভিন্ন কমান্ড কিভাবে ব্যাবহার করা যায় ।  আমার কয়টা হার্ড ডিস্ক আছে আছে সেটা দেখার জন্য list disk লিস্ট থেকে কোন একটা হার্ডডিস্ক কে সিলেক্ট করার জন্য  select Disk 0; ডিস্ক ০ কে সিলেক্ট করবে সিলেক্ট করা হার্ড ডিস্ক এর আন্ডারে কয়টা পার্টিশন আছে সেটা দেখার জন্য list partition primary partition ক্রিয়েট করার জন্য কমান্ড  create partition primary size = sss    এটার ড্রাইভ লেটার দেয়ার জন্য লিখতে হবে assign letter = 'D' এটা কে ntfs এ ফরমেট করার জন্য ল...

উবুন্টুতে রুট পাসওয়ার্ড ভুলে তা রিকভার করার উপায় ।

যদি কেউ রুট পাসওয়ার্ড ভুলে যান তাহলে নিচের কাজ গুলো করে নতুন পাসওয়ার্ড সেট করতে পারবেন: প্রথমে পিসি রিস্টার্ট দিন । দিয়ে UP/DOWN করে kernel version সিলেক্ট করে e চাপুন । ব্ল্যাক Screen আসবে এবার একটা Space দিয়ে লিখুন “Single” [ Enter ] এরপর b চাপুন ফলাফল : লিনাক্সের Single user Mood এ চলে আসছেন । এখন লিখুন passwd root [ Enter ] এখন নতুন পাসওয়ার্ড খানা টাইপ করেন [ এন্টার ] আবার টাইপ করেন [ এন্টার ] কাজ শেষ , এবার reboot টাইপ করেন । এখন নতুন পাসওয়ার্ড দিয়ে লগইন করেন। পুনশ্চ : যদি আপনার উইন্ডোজ এর সাথে ডুয়েল বুট করা থাকে তবে এই প্রক্রিয়া কাজ করবে না ।