জেনারেটর ভাষার সুবিধা যেমন `ফলন` পাওয়া ভাল ধারণা?


9

পিএইচপি, সি #, পাইথন এবং সম্ভবত কয়েকটি অন্যান্য ভাষায় একটি yieldকীওয়ার্ড রয়েছে যা জেনারেটর ফাংশন তৈরি করতে ব্যবহৃত হয়।

পিএইচপি-তে: http://php.net/manual/en/language.generators.syntax.php

পাইথনে: https://www.pythoncentral.io/python-generators- এবং-yeld-keyword/

সি # তে: https://docs.microsoft.com/en-us/dotnet/csharp/language-references/keywords/yeld

আমি উদ্বিগ্ন যে ভাষা বৈশিষ্ট্য / সুবিধা হিসাবে yieldকিছু সম্মেলন ভঙ্গ করে। এর মধ্যে একটি হ'ল আমি "স্পষ্টতা" refer এটি এমন একটি পদ্ধতি যা প্রতিবার আপনি যখন কল করেন তখন আলাদা ফলাফল দেয়। নিয়মিত নন-জেনারেটর ফাংশন সহ আপনি এটিকে কল করতে পারেন এবং যদি এটি একই ইনপুট দেওয়া হয় তবে এটি একই আউটপুট ফেরত দেবে। ফলন সহ, এটি তার অভ্যন্তরীণ অবস্থার উপর নির্ভর করে বিভিন্ন আউটপুট দেয় returns সুতরাং আপনি যদি এলোমেলোভাবে উত্পাদনকারী ফাংশনটি কল করেন, এর পূর্ববর্তী অবস্থাটি না জেনে, আপনি এটি কোনও নির্দিষ্ট ফলাফলের প্রত্যাশা করতে পারবেন না।

এই জাতীয় ফাংশন কীভাবে ভাষার দৃষ্টান্তের সাথে খাপ খায়? এটি আসলে কোনও সম্মেলন ভেঙে দেয়? এই বৈশিষ্ট্যটি ব্যবহার এবং ব্যবহার করা কি ভাল ধারণা? (কোনটি ভাল এবং কী খারাপ, gotoতার উদাহরণ দেওয়ার জন্য একসময় অনেকগুলি ভাষার বৈশিষ্ট্য ছিল এবং এখনও রয়েছে, তবে এটি ক্ষতিকারক হিসাবে বিবেচিত হয় এবং যেমন জাভা কিছু ভাষা থেকে নির্মূল করা হয়েছিল)। প্রোগ্রামিং ল্যাঙ্গুয়েজ সংকলক / দোভাষীকে এই জাতীয় বৈশিষ্ট্যটি বাস্তবায়নের জন্য কোনও কনভেনশন থেকে বেরিয়ে যেতে হবে, উদাহরণস্বরূপ, কোনও ভাষা এই বৈশিষ্ট্যটির কাজ করার জন্য মাল্টি-থ্রেডিং বাস্তবায়ন করতে পারে, বা থ্রেডিং প্রযুক্তি ছাড়াই এটি করা যায়?


4
yieldমূলত একটি স্টেট ইঞ্জিন। এটি প্রতিবার একই ফলাফল ফেরত দেওয়ার উদ্দেশ্যে নয়। এটি নিখুঁত সুনির্দিষ্টতার সাথে যা করবে তা হ'ল প্রতিবারের অনুরোধের সময় পরবর্তী আইটেমটি একটি গণনার মধ্যে ফিরিয়ে আনতে হবে। থ্রেড প্রয়োজন হয় না; আপনার বর্তমান অবস্থা বজায় রাখার জন্য আপনার একটি ক্লোজার (কম বেশি) প্রয়োজন।
রবার্ট হার্ভে

1
"নির্দিষ্টতা" এর মানের হিসাবে বিবেচনা করুন, একই ইনপুট ক্রমটি দেওয়া হলে, পুনরুক্তিকারীকে একটি সিরিজের কলগুলি একই ক্রমে ঠিক একই আইটেমগুলি প্রদান করবে yield
রবার্ট হার্ভে

4
আমি নিশ্চিত নই যে আপনার বেশিরভাগ প্রশ্ন কোথা থেকে এসেছে কারণ সি ++ এর পাইথনের মতো yield কীওয়ার্ড নেই। এটির একটি স্থিতিশীল পদ্ধতি রয়েছে std::this_thread::yield()তবে এটি কোনও কীওয়ার্ড নয়। সুতরাং এটি this_threadএটির প্রায় কোনও কলকে আগে থেকেই সংশোধন করবে, এটি একেবারে সুস্পষ্ট করে তুলবে এটি কেবল একটি থ্রেড ফলনের জন্য একটি লাইব্রেরি বৈশিষ্ট্য, সাধারণভাবে নিয়ন্ত্রণ প্রবাহের ফলন সম্পর্কে কোনও ভাষা বৈশিষ্ট্য নয়।
Ixrec

সি # তে লিঙ্কটি আপডেট হয়েছে, সি ++ এর জন্য একটি সরানো হয়েছে
ডেনিস

উত্তর:


16

ক্যাভেটস প্রথমে - সি # হ'ল ভাষাটি আমি সবচেয়ে ভাল জানি এবং এটির yieldঅন্যান্য ভাষার সাথে খুব মিল রয়েছে বলে মনে হয় yield, তবে আমি অবহিত না এমন সূক্ষ্ম পার্থক্য থাকতে পারে।

আমি উদ্বিগ্ন যে ভাষার বৈশিষ্ট্য / সুবিধা হিসাবে, ফলন কিছু সম্মেলন ভঙ্গ করে। এর মধ্যে একটি হ'ল আমি "স্পষ্টতা" refer এটি এমন একটি পদ্ধতি যা প্রতিবার আপনি যখন কল করেন তখন আলাদা ফলাফল দেয়।

অর্থহীন কথাবার্তা। আপনি যখনই ডাকছেন তখনই কি আপনি সত্যই প্রত্যাশা করছেন Random.Nextবা Console.ReadLineএকই ফল ফিরে আসবেন? রেস্ট কল সম্পর্কে কীভাবে? প্রমাণীকরণ? আইটেম একটি সংগ্রহ বন্ধ? অপরিষ্কার যে সমস্ত ধরণের (ভাল, দরকারী) ফাংশন আছে।

এই জাতীয় ফাংশন কীভাবে ভাষার দৃষ্টান্তের সাথে খাপ খায়? এটি আসলে কোনও সম্মেলন ভেঙে দেয়?

হ্যাঁ, এর yieldসাথে সত্যিই খারাপভাবে অভিনয় করে try/catch/finallyএবং এটি অনুমোদিত নয় ( https://blogs.msdn.microsoft.com/ericlippert/2009/07/16/iterator-blocks-part-three-why-no-yeld-in-finally/ এর জন্য অধিক তথ্য).

এই বৈশিষ্ট্যটি ব্যবহার এবং ব্যবহার করা কি ভাল ধারণা?

এই বৈশিষ্ট্যটি অবশ্যই পাওয়া ভাল ধারণা। সি # এর লিনকিউ-এর মতো জিনিসগুলি সত্যিই দুর্দান্ত - অলসভাবে সংগ্রহগুলি মূল্যায়ন করা একটি বৃহত কার্যকারিতা উপকার সরবরাহ করে এবং yieldএই ধরণের জিনিসটিকে কোডের একটি ভগ্নাংশের সাথে বাগের ভগ্নাংশের সাহায্যে মঞ্জুরি দেয় যা একটি হাত ঘোরানো পুনরুক্তি করবে।

এটি বলেছে, yieldলিনকিউ স্টাইল সংগ্রহের প্রক্রিয়াজাতকরণের বাইরে ব্যবহারের এক টন নেই । আমি এটিকে বৈধতা প্রক্রিয়াজাতকরণ, তফসিল উত্পন্নকরণ, র্যান্ডমাইজেশন এবং আরও কয়েকটি জিনিসের জন্য ব্যবহার করেছি তবে আমি আশা করি যে বেশিরভাগ বিকাশকারী এটি কখনও ব্যবহার করেন নি (বা এটির অপব্যবহার করেছেন)।

প্রোগ্রামিং ল্যাঙ্গুয়েজ সংকলক / দোভাষীকে এই জাতীয় বৈশিষ্ট্যটি বাস্তবায়নের জন্য কোনও কনভেনশন থেকে বেরিয়ে যেতে হবে, উদাহরণস্বরূপ, কোনও ভাষা এই বৈশিষ্ট্যটির কাজ করার জন্য মাল্টি-থ্রেডিং বাস্তবায়ন করতে পারে, বা থ্রেডিং প্রযুক্তি ছাড়াই এটি করা যায়?

বেপারটা এমন না. সংকলকটি একটি স্টেট মেশিন পুনরুক্তি উত্পাদন করে যা এটি কোথায় থামেছে তার উপর নজর রাখে যাতে পরের বার যখন ডাকা হয় তখন এটি আবার শুরু করতে পারে। কোড জেনারেশনের প্রক্রিয়াটি ধারাবাহিকতা পাসিং স্টাইলের অনুরূপ কিছু করে, যেখানে কোডের পরে কোডটি yieldতার নিজের ব্লকে টানানো হয় (এবং যদি এর কোনও yieldএস থাকে, অন্য একটি সাব-ব্লক এবং এই জাতীয় কিছু)। এটি একটি কার্যকর পদ্ধতি যা প্রায়শই ফাংশনাল প্রোগ্রামিংয়ে ব্যবহৃত হয় এবং এটি সি # এর অ্যাসিঙ্ক / সংকলনের অপেক্ষায়ও প্রদর্শিত হয়।

কোনও থ্রেডিংয়ের প্রয়োজন নেই, তবে বেশিরভাগ সংকলকগুলিতে কোড জেনারেশনের জন্য এটির জন্য পৃথক পদ্ধতির প্রয়োজন হয় এবং অন্যান্য ভাষার বৈশিষ্ট্যগুলির সাথে কিছুটা দ্বন্দ্ব রয়েছে।

সব মিলিয়ে, yieldএকটি তুলনামূলকভাবে কম প্রভাবের বৈশিষ্ট্য যা সত্যই সমস্যার নির্দিষ্ট উপসেটটিতে সহায়তা করে।


আমি কখনই সি # গুরুত্ব সহকারে ব্যবহার করি নি তবে এই yieldকীওয়ার্ডটি কর্টিনগুলির সাথে সমান, হ্যাঁ, বা অন্য কিছু? যদি তাই হয় আমি সি একটি ছিল! আমি কোডের কমপক্ষে কিছু শালীন বিভাগের কথা ভাবতে পারি যা এমন ভাষার বৈশিষ্ট্য সহ লিখতে এত সহজ হত।

2
@ ড্রঙ্ককোডার - অনুরূপ, তবে কিছু সীমাবদ্ধতার সাথে, যেমনটা আমি এটি বুঝতে পারি।
টেলাস্টিন

1
আপনিও ফলনটির অপব্যবহার দেখতে চান না। কোনও ভাষার বৈশিষ্ট্য যত বেশি রয়েছে ততই আপনি সেই ভাষায় খারাপভাবে লেখা একটি প্রোগ্রাম দেখতে পাবেন। আমি নিশ্চিত নই যে কোনও অ্যাক্সেসযোগ্য ভাষা লেখার সঠিক পন্থাটি এটিকে আপনার কাছে ফেলে দেওয়া এবং কী লাঠিগুলি দেখেছে।
নিল

1
@ ড্রঙ্ককোডার: এটি আধা-করোটিনগুলির একটি সীমাবদ্ধ সংস্করণ। প্রকৃতপক্ষে, এটি সংকলক দ্বারা সিনট্যাকটিক প্যাটার্ন হিসাবে বিবেচনা করা হয় যা পদ্ধতি কল, শ্রেণি এবং অবজেক্টগুলির একটি সিরিজে প্রসারিত হয়। (মূলত, সংকলকটি একটি ধারাবাহিক অবজেক্ট উত্পন্ন করে যা ক্ষেত্রগুলিতে বর্তমান প্রসঙ্গটি ক্যাপচার করে)) সংগ্রহের জন্য ডিফল্ট বাস্তবায়নটি একটি আধা-কর্টিন, তবে সংকলকটি "ম্যাজিক" পদ্ধতিগুলি ওভারলোড করে, আপনি প্রকৃতপক্ষে আচরণটি কাস্টমাইজ করতে পারেন। উদাহরণস্বরূপ, ভাষায় যুক্ত হওয়ার আগে async/ awaitযুক্ত করার আগে কেউ এটিকে ব্যবহার করে প্রয়োগ করেছে yield
Jörg W Mittag

1
@ নীল সাধারণত কোনও প্রোগ্রামিং ভাষার বৈশিষ্ট্যটির অপব্যবহার করা সম্ভব। আপনি যা বলেছেন তা যদি সত্য হয় তবে পাইথন বা সি # এর তুলনায় সি ব্যবহার করে খারাপভাবে প্রোগ্রাম করা আরও কঠিন হবে, তবে এটি তেমন নয় কারণ সেই ভাষাগুলিতে প্রচুর সরঞ্জাম রয়েছে যা প্রোগ্রামারদের অনেক ভুল থেকে রক্ষা করে যা খুব সহজ are সি দিয়ে তৈরি করতে বাস্তবে, খারাপ প্রোগ্রামগুলির কারণটি খারাপ প্রোগ্রামাররা - এটি বেশ ভাষা-অজ্ঞাত সমস্যা।
বেন কটরেল

12

একটি জেনারেটর ভাষার সুবিধা যেমন yieldএকটি ভাল ধারণা আছে?

আমি জোর দিয়ে হ্যাঁ, পাইথনের দৃষ্টিকোণ থেকে এর উত্তর দিতে চাই , এটি দুর্দান্ত ধারণা

আমি প্রথমে আপনার প্রশ্নে কিছু প্রশ্ন এবং অনুমানকে সম্বোধন করে শুরু করব, তারপরে পাইথনে জেনারেটরগুলির ব্যাপকতা এবং তাদের অযৌক্তিক উপযোগিতা প্রদর্শন করব।

নিয়মিত নন-জেনারেটর ফাংশন সহ আপনি এটিকে কল করতে পারেন এবং যদি এটি একই ইনপুট দেওয়া হয় তবে এটি একই আউটপুট ফেরত দেবে। ফলন সহ, এটি তার অভ্যন্তরীণ অবস্থার উপর নির্ভর করে বিভিন্ন আউটপুট দেয় returns

এটা মিথ্যা। বস্তুগুলির পদ্ধতিগুলি তাদের নিজস্ব অভ্যন্তরীণ অবস্থার সাথে ফাংশন হিসাবে বিবেচনা করা যেতে পারে। পাইথনে, যেহেতু সবকিছুই একটি বস্তু, তাই আপনি আসলে কোনও বস্তুর কাছ থেকে কোনও পদ্ধতি পেতে পারেন এবং সেই পদ্ধতিটি ঘিরে ফেলতে পারেন (এটি যে বস্তুটি এসেছে সেটির সাথে আবদ্ধ, সুতরাং এটি তার অবস্থার কথা মনে রাখে)।

অন্যান্য উদাহরণগুলির মধ্যে ইচ্ছাকৃতভাবে এলোমেলো ফাংশনগুলির পাশাপাশি নেটওয়ার্ক, ফাইল সিস্টেম এবং টার্মিনালের মতো ইনপুট পদ্ধতি অন্তর্ভুক্ত রয়েছে।

এই জাতীয় ফাংশন কীভাবে ভাষার দৃষ্টান্তের সাথে খাপ খায়?

ভাষার দৃষ্টান্ত যদি প্রথম শ্রেণির ফাংশনগুলির মতো জিনিসগুলিকে সমর্থন করে এবং জেনারেটরগুলি ইটারেবল প্রোটোকলের মতো অন্যান্য ভাষার বৈশিষ্ট্যগুলিকে সমর্থন করে তবে তারা নির্বিঘ্নে ফিট করে।

এটি আসলে কোনও সম্মেলন ভেঙে দেয়?

না, যেহেতু এটি ভাষায় বেকড রয়েছে, কনভেনশনগুলি চারপাশে নির্মিত এবং এতে জেনারেটরগুলির ব্যবহার (বা প্রয়োজন!) অন্তর্ভুক্ত।

প্রোগ্রামিং ল্যাঙ্গুয়েজ সংকলক / দোভাষীকে এই জাতীয় বৈশিষ্ট্যটি বাস্তবায়নের জন্য কোনও কনভেনশন থেকে বেরিয়ে আসতে হবে

অন্য কোনও বৈশিষ্ট্যের মতো, সংকলকটি কেবল বৈশিষ্ট্যটি সমর্থন করার জন্য ডিজাইন করা দরকার। পাইথনের ক্ষেত্রে, ফাংশনগুলি ইতিমধ্যে রাষ্ট্রযুক্ত অবজেক্ট (যেমন ডিফল্ট আর্গুমেন্ট এবং ফাংশন টীকা)।

এই বৈশিষ্ট্যটির কাজ করার জন্য কোনও ভাষার কী মাল্টি-থ্রেডিং বাস্তবায়ন করতে হবে, বা থ্রেডিং প্রযুক্তি ছাড়াই এটি করা যেতে পারে?

মজাদার ঘটনা: ডিফল্ট পাইথন বাস্তবায়ন থ্রেডিং মোটেও সমর্থন করে না। এটিতে একটি গ্লোবাল ইন্টারপ্রেটার লক (জিআইএল) বৈশিষ্ট্যযুক্ত, তাই পাইথনের অন্য কোনও উদাহরণ চালানোর জন্য আপনি দ্বিতীয় প্রক্রিয়াটি ব্যয় না করে আসলে কিছুই একই সাথে চলমান হয় না।


দ্রষ্টব্য: উদাহরণ পাইথন 3 এ রয়েছে

ফলনের বাইরে

যদিও yieldশব্দ কোন ফাংশন ব্যবহার করা যেতে পারে এটি একটি জেনারেটর পরিণত, এটা এক করতে একমাত্র উপায় নয়। পাইথন জেনারেটর এক্সপ্রেশন বৈশিষ্ট্যযুক্ত, অন্য পুনরাবৃত্ত (অন্যান্য জেনারেটর সহ) এর ক্ষেত্রে জেনারেটর স্পষ্টভাবে প্রকাশ করার একটি শক্তিশালী উপায়

>>> pairs = ((x,y) for x in range(10) for y in range(10) if y >= x)
>>> pairs
<generator object <genexpr> at 0x0311DC90>
>>> sum(x*y for x,y in pairs)
1155

আপনি দেখতে পাচ্ছেন, সিনট্যাক্সটি কেবল পরিষ্কার এবং পঠনযোগ্য নয়, sumজেনারেটর গ্রহণের মতো বিল্ট-ইন ফাংশন ।

সঙ্গে

উইথ স্টেটমেন্টের জন্য পাইথন এনহান্সমেন্ট প্রস্তাবটি দেখুন । আপনি অন্যান্য ভাষায় উইথ স্টেটমেন্ট থেকে আশা করতে পারেন তার চেয়ে এটি অনেক আলাদা different স্ট্যান্ডার্ড লাইব্রেরি থেকে সামান্য সহায়তায় পাইথনের জেনারেটর তাদের জন্য প্রসঙ্গ পরিচালক হিসাবে সুন্দরভাবে কাজ করে।

>>> from contextlib import contextmanager
>>> @contextmanager
def debugWith(arg):
        print("preprocessing", arg)
        yield arg
        print("postprocessing", arg)


>>> with debugWith("foobar") as s:
        print(s[::-1])


preprocessing foobar
raboof
postprocessing foobar

অবশ্যই, মুদ্রণ জিনিসগুলি আপনি এখানে করতে পারেন এমন সবচেয়ে বিরক্তিকর জিনিস সম্পর্কে তবে এটি দৃশ্যমান ফলাফল দেখায়। আরও আকর্ষণীয় বিকল্পগুলির মধ্যে সম্পদের স্বয়ংক্রিয় ব্যবস্থাপনার (ফাইলগুলি / স্ট্রিমগুলি / নেটওয়ার্ক সংযোগগুলি খোলার এবং বন্ধ করা), সমাবর্তনের জন্য লক করা, অস্থায়ীভাবে মোড়ক বা কোনও ফাংশন প্রতিস্থাপন এবং সংশোধন করে ডেটা পুনরায় সংক্ষেপণ অন্তর্ভুক্ত রয়েছে। যদি কলিং ফাংশনগুলি আপনার কোডে ইনজেকশন কোডের মতো হয়, তবে বিবৃতি সহ অন্য কোডে আপনার কোডের অংশগুলি মোড়ানো করার মতো। তবে আপনি এটি ব্যবহার করুন, এটি কোনও ভাষা কাঠামোর মধ্যে সহজ হুকের শক্ত উদাহরণ। ফলন-ভিত্তিক জেনারেটর প্রসঙ্গ পরিচালকগণ তৈরি করার একমাত্র উপায় নয়, তবে তারা অবশ্যই একটি সুবিধাজনক।

জন্য এবং আংশিক ক্লান্তি

পাইথনের লুপগুলির জন্য একটি আকর্ষণীয় উপায়ে কাজ করুন। তাদের নিম্নলিখিত ফর্ম্যাট আছে:

for <name> in <iterable>:
    ...

প্রথমত, আমি যে অভিব্যক্তিটি বলেছিলাম <iterable>তা পুনরাবৃত্তিযোগ্য অবজেক্ট পাওয়ার জন্য মূল্যায়ন করা হয়। দ্বিতীয়ত, পুনরাবৃত্তকারী __iter__এটিতে ডেকেছিল এবং ফলস্বরূপ পুনরাবৃত্তকারীগুলি পর্দার আড়ালে সঞ্চিত থাকে। এরপরে, __next__আপনাকে যে নামটি দেওয়া হয়েছিল তার সাথে আবদ্ধ হওয়ার জন্য একটি মান পেতে পুনরুত্থককে ডাকা হয় <name>। এই পদক্ষেপটি পুনরুদ্ধার না করা অবধি কলটি __next__a নিক্ষেপ করবে StopIteration। ব্যতিক্রমটি লুপটির জন্য গিলে ফেলেছে এবং সেখান থেকে কার্যকর করা চলে।

জেনারেটরগুলিতে ফিরে আসছেন: আপনি যখন __iter__কোনও জেনারেটরে কল করেন, এটি কেবল নিজের কাছে ফিরে আসে।

>>> x = (a for a in "boring generator")
>>> id(x)
51502272
>>> id(x.__iter__())
51502272

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

>>> generator = (x for x in 'more boring stuff')
>>> for letter in generator:
        print(ord(letter))
        if letter > 'p':
                break


109
111
114
>>> for letter in generator:
        print(letter)


e

b
o
r
i
n
g

s
t
u
f
f

অলস মূল্যায়ন

তালিকার সাথে তুলনায় জেনারেটরগুলির নীচের দিকগুলির একটি হ'ল আপনি কোনও জেনারেটরে অ্যাক্সেস করতে পারবেন কেবল তার পরের জিনিসটি of আপনি আর আগের ফলাফল হিসাবে ফিরে যেতে পারবেন না, বা মধ্যবর্তী ফলাফলগুলি না পেরিয়ে কোনও একটিতে এগিয়ে যান। এর উপরের অংশটি একটি জেনারেটর এর সমতুল্য তালিকার তুলনায় প্রায় কোনও স্মৃতি নিতে পারে না।

>>> import sys
>>> sys.getsizeof([x for x in range(10000)])
43816
>>> sys.getsizeof(range(10000000000))
24
>>> sys.getsizeof([x for x in range(10000000000)])
Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    sys.getsizeof([x for x in range(10000000000)])
  File "<pyshell#10>", line 1, in <listcomp>
    sys.getsizeof([x for x in range(10000000000)])
MemoryError

জেনারেটরগুলিও অলসভাবে বেঁধে রাখা যেতে পারে।

logfile = open("logs.txt")
lastcolumn = (line.split()[-1] for line in logfile)
numericcolumn = (float(x) for x in lastcolumn)
print(sum(numericcolumn))

প্রথম, দ্বিতীয় এবং তৃতীয় রেখাগুলি কেবল প্রতিটি জেনারেটর সংজ্ঞায়িত করে তবে কোনও আসল কাজ করে না। যখন শেষ লাইনটি ডাকা হয়, যোগফলের জন্য একটি সংখ্যাটির জন্য সংখ্যার কলম জিজ্ঞাসা করে, সংখ্যার কলামটি লাস্টক্লম থেকে একটি মান প্রয়োজন, লাস্টক্লম লগফাইলে একটি মান জিজ্ঞাসা করে, যা আসলে ফাইলটি থেকে একটি লাইন পড়ে। যোগফলটি প্রথম পূর্ণসংখ্যা না পাওয়া পর্যন্ত এই স্ট্যাকটি উন্মুক্ত করা হয়। তারপরে, প্রক্রিয়াটি আবার দ্বিতীয় লাইনের জন্য ঘটে। এই মুহুর্তে, যোগফলের দুটি পূর্ণসংখ্যা থাকে এবং এটি তাদের একসাথে যুক্ত করে। নোট করুন যে তৃতীয় লাইনটি এখনও ফাইল থেকে পড়েনি। এরপরে অঙ্কগুলি অঙ্কের কলামটি (অবধি চেনের সম্পূর্ণ অংশ থেকে পুরোপুরি অবজ্ঞাত) থেকে অনুরোধ করে এবং সংখ্যার ক্রম অবসন্ন না হওয়া পর্যন্ত এগুলি যুক্ত করে চলেছে Sum

এখানে সত্যই আকর্ষণীয় অংশটি হ'ল লাইনগুলি পৃথকভাবে পড়া, গ্রাস করা এবং ফেলে দেওয়া হয়। কোনও মুহুর্তে পুরো ফাইলটি একবারে মেমরির মধ্যে নেই। এই লগ ফাইলটি বলুন, একটি টেরাবাইট হলে কী হবে? এটি কেবল কাজ করে, কারণ এটি একবারে কেবল একটি লাইন পড়ে।

উপসংহার

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

আমি বিশ্বাস করি যে এটি নির্ধারণ করার পক্ষে যথেষ্ট যে আপনার জেনারেটরগুলি একটি পরিষ্কারভাবে সংহত, দরকারী ভাষা বৈশিষ্ট্য হিসাবে থাকতে পারে।


6

আপনি যদি ক্লাসিক ওওপি ভাষাগুলি, জেনারেটরগুলিতে ব্যবহার হয়ে থাকেন এবং তা yieldব্যাহত হয় বলে মনে হচ্ছে কারণ পরিবর্তনের স্থিতি বস্তুর স্তরের পরিবর্তে ফাংশন স্তরে ধরা পড়ে।

"নিশ্চিততা" এর প্রশ্নটি যদিও একটি লাল উত্তেজনা। এটিকে সাধারণত রেফারেনশিয়াল স্বচ্ছতা বলা হয় এবং মূলত ফাংশনটি একই যুক্তির জন্য সর্বদা একই ফল দেয়। আপনার পরিবর্তনীয় অবস্থা হওয়ার সাথে সাথে আপনি রেফারেন্সিয়াল স্বচ্ছতা হারাবেন। ওওপি-তে, অবজেক্টগুলির প্রায়শই পারস্পরিক পরিবর্তন ঘটে যায় যার অর্থ মেথড কলের ফলাফল কেবল যুক্তিগুলির উপর নির্ভর করে না, তবে অবজেক্টের অভ্যন্তরীণ অবস্থাও নির্ভর করে।

প্রশ্নটি কোথায় পরিবর্তনযোগ্য রাজ্যটি ক্যাপচার করবে। একটি ক্লাসিক ওওপিতে, অবজেক্ট পর্যায়ে পরিবর্তনযোগ্য অবস্থা বিদ্যমান exist তবে যদি কোনও ভাষা সমর্থন বন্ধ করে দেয় তবে ফাংশন স্তরে আপনার পরিবর্তনীয় অবস্থা থাকতে পারে। জাভাস্ক্রিপ্ট উদাহরণস্বরূপ:

function getCounter() {
   var cnt = 1;
   return function(){ return cnt++; }
}
var counter = getCounter();
counter() --> 1
counter() --> 2

সংক্ষেপে, yieldএমন ভাষায় প্রাকৃতিক যা ক্লোজারগুলিকে সমর্থন করে তবে জাভা-র পুরানো সংস্করণের মতো ভাষায় এমন জায়গা থেকে দূরে থাকবে যেখানে কেবলমাত্র অবজেক্টের স্তরে পরিবর্তিত অবস্থা বিদ্যমান।


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

0

আমার মতে এটি ভাল বৈশিষ্ট্য নয়। এটি একটি খারাপ বৈশিষ্ট্য, প্রাথমিকভাবে কারণ এটি খুব সাবধানতার সাথে শেখানো দরকার এবং প্রত্যেকে এটিকে ভুল শিক্ষা দেয়। "জেনারেটর" শব্দটি লোকেরা জেনারেটর ফাংশন এবং জেনারেটরের বস্তুর মধ্যে দ্বিখণ্ডিত করে। প্রশ্নটি: ঠিক কে বা কী আসল ফলন করছেন?

এটি নিছক আমার মতামত নয়। এমনকি গাইডো, পিইপি বুলেটিনে যেখানে তিনি এ সম্পর্কে বিধি রেখেছেন, স্বীকার করেছেন যে জেনারেটরের কাজটি জেনারেটর নয় বরং একটি "জেনারেটর কারখানা"।

এ জাতীয় গুরুত্বপূর্ণ, আপনি কি ভাবেন না? তবে সেখানে 99% ডকুমেন্টেশন পড়ার পরে আপনি এই ধারণাটি পেয়ে যাবেন যে জেনারেটর ফাংশনটি আসল জেনারেটর এবং তারা আপনাকেও জেনারেটরের কোনও প্রয়োজনের বিষয়টি এড়িয়ে যাওয়ার ঝোঁক দেয়।

গিডো এই ফাংশনগুলির জন্য "জেন" এর পরিবর্তে "ডিএফ" প্রতিস্থাপনের বিষয়টি বিবেচনা করে বলেছিলেন এবং না। তবে আমি যুক্তি দিয়ে বলছি যে এটি যেভাবে যথেষ্ট হত না। এটি সত্যই হওয়া উচিত:

def make_gen(args)
    def_gen foo
        # Put in "yield" and other beahvior
    return_gen foo
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.