পাইথন জেনারেটরের কার্যকারিতা ব্যাখ্যা করার জন্য এই পোস্টটি ফিবোনাচি নম্বরগুলি একটি সরঞ্জাম হিসাবে ব্যবহার করবে ।
এই পোস্টে সি ++ এবং পাইথন কোড উভয়ই প্রদর্শিত হবে।
ফিবোনাচি সংখ্যাগুলি ক্রম হিসাবে সংজ্ঞায়িত করা হয়: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ....
বা সাধারণভাবে:
F0 = 0
F1 = 1
Fn = Fn-1 + Fn-2
এটি অত্যন্ত সহজেই একটি সি ++ ফাংশনে স্থানান্তরিত হতে পারে:
size_t Fib(size_t n)
{
//Fib(0) = 0
if(n == 0)
return 0;
//Fib(1) = 1
if(n == 1)
return 1;
//Fib(N) = Fib(N-2) + Fib(N-1)
return Fib(n-2) + Fib(n-1);
}
তবে আপনি যদি প্রথম ছয়টি ফিবোনাচি নম্বর মুদ্রণ করতে চান তবে উপরের ফাংশনটি দিয়ে আপনি প্রচুর মান পুনরায় গণনা করবেন।
উদাহরণস্বরূপ: Fib(3) = Fib(2) + Fib(1)
তবে পুনরায় Fib(2)
গণনা করা হয় Fib(1)
। আপনি যত বেশি মান গণনা করতে চান, ততই খারাপ আপনি হবেন।
সুতরাং কেউ রাষ্ট্রকে ট্র্যাক করে উপরের লেখার প্রলোভনে পড়তে পারে main
।
// Not supported for the first two elements of Fib
size_t GetNextFib(size_t &pp, size_t &p)
{
int result = pp + p;
pp = p;
p = result;
return result;
}
int main(int argc, char *argv[])
{
size_t pp = 0;
size_t p = 1;
std::cout << "0 " << "1 ";
for(size_t i = 0; i <= 4; ++i)
{
size_t fibI = GetNextFib(pp, p);
std::cout << fibI << " ";
}
return 0;
}
তবে এটি খুব কুরুচিপূর্ণ এবং এটি আমাদের যুক্তিগুলিকে জটিল করে তোলে main
। আমাদের main
ফাংশনে রাষ্ট্র সম্পর্কে উদ্বিগ্ন না হওয়াই ভাল ।
আমরা vector
মানগুলির একটি ফিরিয়ে দিতে পারি এবং মানগুলির iterator
সেটের উপরে পুনরাবৃত্তি করতে একটি ব্যবহার করতে পারি, তবে এর জন্য রিটার্ন মানগুলির একটি বৃহত সংখ্যার জন্য একবারে অনেকগুলি স্মৃতি দরকার।
সুতরাং আমাদের পুরানো পদ্ধতির দিকে ফিরে, আমরা সংখ্যা মুদ্রণ ছাড়াও অন্য কিছু করতে চাইলে কি হবে? আমাদের কোডের পুরো ব্লকটি অনুলিপি করে পেস্ট করতে main
হবে এবং আউটপুট স্টেটমেন্টগুলিকে আমাদের অন্য যা করতে হবে তা পরিবর্তন করতে হবে। এবং যদি আপনি কোডটি অনুলিপি করে আটকান, তবে আপনাকে গুলি করা উচিত। আপনি গুলি করতে চান না, তাই না?
এই সমস্যাগুলি সমাধান করার জন্য, এবং গুলি চালানো এড়াতে, আমরা কলব্যাক ফাংশন ব্যবহার করে কোডের এই ব্লকটি আবার লিখতে পারি। প্রতিবার নতুন ফিবোনাচি নম্বর আসার পরে আমরা কলব্যাক ফাংশনটি কল করব call
void GetFibNumbers(size_t max, void(*FoundNewFibCallback)(size_t))
{
if(max-- == 0) return;
FoundNewFibCallback(0);
if(max-- == 0) return;
FoundNewFibCallback(1);
size_t pp = 0;
size_t p = 1;
for(;;)
{
if(max-- == 0) return;
int result = pp + p;
pp = p;
p = result;
FoundNewFibCallback(result);
}
}
void foundNewFib(size_t fibI)
{
std::cout << fibI << " ";
}
int main(int argc, char *argv[])
{
GetFibNumbers(6, foundNewFib);
return 0;
}
এটি স্পষ্টতই একটি উন্নতি, আপনার যুক্তিটি main
বিশৃঙ্খলাযুক্ত নয় এবং আপনি ফিবোনাচি সংখ্যাগুলি দিয়ে যা কিছু করতে চান, কেবল নতুন কলব্যাকগুলি সংজ্ঞায়িত করতে পারেন।
তবে এটি এখনও নিখুঁত নয়। আপনি যদি কেবল প্রথম দুটি ফিবোনাচি নম্বর পেতে এবং তারপরে কিছু করতে চান, তবে আরও কিছু পেতে চান, তবে অন্য কিছু করুন?
ঠিক আছে, আমরা যেমন চলি তেমন চলতে পারি এবং আমরা আবার রাষ্ট্র যুক্ত করতে শুরু করতে পারলাম, এবং main
ফেইসবুক নম্বরগুলি একটি স্বেচ্ছাসেবী বিন্দু থেকে শুরু করতে পারব। তবে এটি আমাদের কোডটিকে আরও ফাটিয়ে দেবে এবং ফিবোনাচি সংখ্যা মুদ্রণের মতো কোনও সাধারণ কাজের জন্য এটি ইতিমধ্যে বড় দেখায়।
আমরা কয়েক থ্রেডের মাধ্যমে একটি প্রযোজক এবং ভোক্তা মডেলটি প্রয়োগ করতে পারি। তবে এটি কোডটিকে আরও জটিল করে তোলে।
পরিবর্তে জেনারেটর সম্পর্কে কথা বলা যাক।
পাইথনের একটি খুব সুন্দর ভাষা বৈশিষ্ট্য রয়েছে যা এই নামক জেনারেটরের মতো সমস্যার সমাধান করে।
একটি জেনারেটর আপনাকে একটি ফাংশন সম্পাদন করতে, একটি স্বেচ্ছাসেবী বিন্দুতে থামতে দেয় এবং তারপরে আপনি যেখানে রেখেছিলেন সেখানে আবার চালিয়ে যাওয়ার অনুমতি দেয়। প্রতিটি সময় একটি মান ফেরত।
নিম্নলিখিত কোডটি বিবেচনা করুন যা একটি জেনারেটর ব্যবহার করে:
def fib():
pp, p = 0, 1
while 1:
yield pp
pp, p = p, pp+p
g = fib()
for i in range(6):
g.next()
যা আমাদের ফলাফল দেয়:
0 1 1 2 3 5
yield
বিবৃতি পাইথন জেনারেটর দিয়ে conjuction ব্যবহার করা হয়। এটি ফাংশনের স্থিতি সংরক্ষণ করে এবং ইয়েল্ডযুক্ত মান প্রদান করে। পরের বার আপনি জেনারেটরে পরবর্তী () ফাংশনটি কল করবেন, ফলনটি যেখানে ছেড়ে গেছে সেখানেই এটি চালিয়ে যাবে।
এটি কলব্যাক ফাংশন কোডের চেয়ে অনেক বেশি পরিষ্কার। আমাদের ক্লিনার কোড রয়েছে, ছোট কোড রয়েছে এবং আরও বেশি কার্যকরী কোডের উল্লেখ না করা (পাইথন নির্বিচারে বড় সংখ্যার অনুমতি দেয়)।
উৎস
send
যে কোনও জেনারেটরে ডেটা পাওয়া সম্ভব । একবার আপনি এটি করেন যে আপনার একটি 'কর্টিন' রয়েছে। উল্লিখিত গ্রাহক / প্রযোজকের মতো কর্টিনগুলির সাথে নিদর্শনগুলি প্রয়োগ করা খুব সহজ কারণ তাদের কোনও প্রয়োজন নেইLock
এবং তাই অচলাবস্থা রাখতে পারে না। থ্রেড বাজানো ছাড়াই কর্টিনগুলি বর্ণনা করা শক্ত, তাই আমি কেবলই বলব যে কর্টাইনগুলি থ্রেডিংয়ের জন্য খুব মার্জিত বিকল্প alternative