मेमोरी का उपयोग कैसे कम करें और जनरेटर का उपयोग करके पायथन कोड को गति दें

सभी को नमस्कार। आज हम एक उपयोगी अनुवाद साझा करना चाहते हैं, जो पाठ्यक्रम के लॉन्च से पहले तैयार किया गया है "पायथन में वेब-डेवलपर" वेब एप्लिकेशन बनाते समय, मशीन लर्निंग मॉडल, या परीक्षण करते समय पायथन में समय-कुशल और मेमोरी-कुशल कोड लिखना विशेष रूप से महत्वपूर्ण है।



जब मैंने पायथन में जनरेटर सीखना शुरू किया, तो मुझे नहीं पता था कि वे कितने महत्वपूर्ण थे। हालाँकि, उन्होंने मुझे मशीन लर्निंग के माध्यम से अपनी पूरी यात्रा में लेखन कार्यों में लगातार मदद की।


जेनरेटर फ़ंक्शन आपको एक फ़ंक्शन की घोषणा करने की अनुमति देता है जो एक पुनरावृत्त की तरह व्यवहार करेगा। वे प्रोग्रामर को तेज, सरल और स्वच्छ चलने वाले बनाने के लिए अनुमति देते हैं। एक पुनरावृत्ति एक वस्तु है जिसे दोहराया जा सकता है (लूप किया गया)। इसका उपयोग डेटा कंटेनर को अमूर्त करने और इसे चलने योग्य वस्तु की तरह व्यवहार करने के लिए किया जाता है। उदाहरण के लिए, एक चलने योग्य वस्तु का एक उदाहरण तार, सूची और शब्दकोशों हो सकता है।


जनरेटर एक फ़ंक्शन की तरह दिखता है, लेकिन रिटर्न के बजाय उपज कीवर्ड का उपयोग करता है। आइए इसे स्पष्ट करने के लिए एक उदाहरण देखें।


def generate_numbers(): n = 0 while n < 3: yield n n += 1 

यह एक जनरेटर फ़ंक्शन है। जब आप इसे कॉल करते हैं, तो यह एक जनरेटर ऑब्जेक्ट लौटाता है।


 >>> numbers = generate_numbers() >>> type(numbers) <class 'generator'> 

यह ध्यान देना महत्वपूर्ण है कि जनरेटर फ़ंक्शन के शरीर में राज्य कैसे समझाया जाता है। आप बिल्ट-इन नेक्स्ट () फ़ंक्शन का उपयोग करके एक समय में एक को पुन: व्यवस्थित कर सकते हैं:


 >>> next_number = generate_numbers() >>> next(next_number) 0 >>> next(next_number) 1 >>> next(next_number) 2 

यदि आप निष्पादन के अंत के बाद अगले () कॉल करते हैं तो क्या होगा?


StopIteration एक बिल्ट-इन प्रकार का अपवाद है जो जनरेटर के परिणामस्वरूप स्वचालित रूप से होते ही स्वचालित रूप से होता है। यह लूप के लिए एक स्टॉप सिग्नल है।


यील्ड स्टेटमेंट


इसका मुख्य कार्य जनरेटर फ़ंक्शन के प्रवाह को नियंत्रित करना है ताकि यह रिटर्न स्टेटमेंट की तरह दिखे। जब एक जनरेटर फ़ंक्शन को बुलाया जाता है या एक जनरेटर अभिव्यक्ति का उपयोग किया जाता है, तो यह जनरेटर नामक एक विशेष पुनरावृत्ति देता है। एक जनरेटर का उपयोग करने के लिए, इसे कुछ चर में असाइन करें। जनरेटर में विशेष तरीकों को कॉल करते समय, जैसे कि अगले (), फ़ंक्शन कोड को उपज तक निष्पादित किया जाएगा।


जब यह उपज स्टेटमेंट में जाता है, तो प्रोग्राम फ़ंक्शन को रोक देता है और उस ऑब्जेक्ट का मान लौटाता है जिसने निष्पादन शुरू किया था। (जबकि रिटर्न फ़ंक्शन के निष्पादन को पूरी तरह से रोक देता है।) जब फ़ंक्शन निलंबित हो जाता है, तो इसकी स्थिति संरक्षित है।


अब जब हम पायथन में जनरेटर से परिचित हैं, तो आइए सामान्य दृष्टिकोण की तुलना करें जो कि कोड निष्पादन पर खर्च किए जाने वाले स्मृति और समय के संदर्भ में जनरेटर का उपयोग करता है।


समस्या कथन


मान लीजिए कि हमें संख्याओं की एक बड़ी सूची (उदाहरण के लिए, 100000000) के माध्यम से जाने की जरूरत है और उन सभी संख्याओं के वर्गों को बचाना है जिन्हें किसी अन्य सूची में अलग से संग्रहीत करने की आवश्यकता है।


सामान्य दृष्टिकोण


 import memory_profiler import time def check_even(numbers): even = [] for num in numbers: if num % 2 == 0: even.append(num*num) return even if __name__ == '__main__': m1 = memory_profiler.memory_usage() t1 = time.clock() cubes = check_even(range(100000000)) t2 = time.clock() m2 = memory_profiler.memory_usage() time_diff = t2 - t1 mem_diff = m2[0] - m1[0] print(f"It took {time_diff} Secs and {mem_diff} Mb to execute this method") 

उपरोक्त कोड चलाने के बाद, हमें निम्नलिखित मिलते हैं:


 It took 21.876470000000005 Secs and 1929.703125 Mb to execute this method 

जनरेटर का उपयोग करना


 import memory_profiler import time def check_even(numbers): for num in numbers: if num % 2 == 0: yield num * num if __name__ == '__main__': m1 = memory_profiler.memory_usage() t1 = time.clock() cubes = check_even(range(100000000)) t2 = time.clock() m2 = memory_profiler.memory_usage() time_diff = t2 - t1 mem_diff = m2[0] - m1[0] print(f"It took {time_diff} Secs and {mem_diff} Mb to execute this method") 

उपरोक्त कोड चलाने के बाद, हमें निम्नलिखित मिलते हैं:


 It took 2.9999999995311555e-05 Secs and 0.02656277 Mb to execute this method 

जैसा कि हम देख सकते हैं, रनटाइम और मेमोरी का उपयोग काफी कम हो गया है। जनरेटर एक सिद्धांत पर काम करते हैं, जिसे "आलसी कंप्यूटिंग" कहा जाता है। इसका मतलब है कि वे प्रोसेसर, मेमोरी और अन्य कंप्यूटिंग संसाधनों को बचा सकते हैं।


निष्कर्ष


मुझे आशा है कि इस लेख में मैं यह दिखाने में सक्षम था कि पायथन में जनरेटर का उपयोग स्मृति और समय जैसे संसाधनों को बचाने के लिए कैसे किया जा सकता है। यह लाभ इस तथ्य के कारण दिखाई देता है कि जनरेटर मेमोरी में सभी परिणामों को संग्रहीत नहीं करते हैं, लेकिन उन्हें मक्खी पर गणना करते हैं, और मेमोरी का उपयोग केवल तभी किया जाता है जब हम गणनाओं के परिणाम का अनुरोध करते हैं। जेनरेटर आपको बॉयलरप्लेट कोड की एक बड़ी मात्रा को भी सार करने की अनुमति देते हैं, जो कि पुनरावृत्तियों को लिखने के लिए आवश्यक है, इसलिए वे कोड की मात्रा को कम करने में भी मदद करते हैं।

Source: https://habr.com/ru/post/hi477926/


All Articles