यह पोस्ट पायथन जनरेटर की उपयोगिता को समझाने के लिए एक उपकरण के रूप में फाइबोनैचि संख्याओं का उपयोग करेगा ।
इस पोस्ट में C ++ और पायथन कोड दोनों की सुविधा होगी।
फाइबोनैचि संख्याओं को अनुक्रम के रूप में परिभाषित किया गया है: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ...।
या सामान्य रूप में:
F0 = 0
F1 = 1
Fn = Fn-1 + Fn-2
इसे बेहद आसानी से C ++ फ़ंक्शन में स्थानांतरित किया जा सकता है:
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
आउटपुट स्टेटमेंट को जो कुछ भी हम करना चाहते हैं उसे बदल सकते हैं। और यदि आप कोड को कॉपी और पेस्ट करते हैं, तो आपको गोली मार दी जानी चाहिए। आप गोली नहीं चलाना चाहते, क्या आप?
इन समस्याओं को हल करने के लिए, और शॉट लेने से बचने के लिए, हम कॉलबैक फ़ंक्शन का उपयोग करके कोड के इस ब्लॉक को फिर से लिख सकते हैं। जब भी कोई नया फाइबोनैचि नंबर आता है, हम कॉलबैक फ़ंक्शन को कॉल करेंगे।
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
, जिससे GetFibNumbers को एक मध्यस्थ बिंदु से शुरू किया जा सके। लेकिन यह हमारे कोड को और प्रस्फुटित करेगा, और यह पहले से ही फाइबोनैचि संख्याओं को प्रिंट करने जैसे सरल कार्य के लिए बहुत बड़ा है।
हम धागे के एक जोड़े के माध्यम से एक निर्माता और उपभोक्ता मॉडल को लागू कर सकते हैं। लेकिन इससे कोड और भी जटिल हो जाता है।
इसके बजाय चलो जनरेटर के बारे में बात करते हैं।
पायथन में एक बहुत अच्छी भाषा की सुविधा है जो इन जेनरेटर नामक समस्याओं को हल करती है।
एक जनरेटर आपको एक फ़ंक्शन निष्पादित करने, एक मनमाना बिंदु पर रुकने, और फिर फिर से जारी रखने की अनुमति देता है जहां आपने छोड़ा था। हर बार एक मान लौटाते हुए।
जनरेटर का उपयोग करने वाले निम्नलिखित कोड पर विचार करें:
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
और इसलिए गतिरोध नहीं हो सकता है। धागे को कोसने के बिना कोरटाइन का वर्णन करना कठिन है, इसलिए मैं सिर्फ कहूंगा कि कोरआउट थ्रेडिंग का एक बहुत ही सुंदर विकल्प है।