म्यूटेबल डिफ़ॉल्ट आर्ग्युमेंट्स
जब आप Python में म्यूटेबल आर्ग्युमेंट्स को डिफ़ॉल्ट आर्ग्युमेंट्स के साथ मिलाते हैं, तो यह कुछ अप्रत्याशित परिणाम दे सकता है।
आइए इसे एक सरल उदाहरण से समझते हैं। मान लीजिए आप एक शिक्षक हैं और आप एक फ़ंक्शन बनाना चाहते हैं जो विभिन्न असाइनमेंट्स के लिए छात्रों के स्कोर रिकॉर्ड करे। आप इन स्कोरों को ट्रैक करने के लिए एक लिस्ट का उपयोग करना चाहते हैं। इसलिए, आप प्रारंभ में कुछ इस तरह लिख सकते हैं:
def record_score(new_score, score_list=[]):
score_list.append(new_score)
return score_list
print(record_score(95)) # [95]
print(record_score(85)) # [95, 85]
यह देखने में ठीक लगता है। फ़ंक्शन
record_score
एक स्कोर और एक लिस्ट लेता है। यदि कोई लिस्ट प्रदान नहीं की जाती है, तो यह एक खाली लिस्ट इस्तेमाल करता है (फ़ंक्शन डेफ़िनिशन में score_list=[]
से)।जब आप
record_score(95)
को कॉल करते हैं, तो ऐसा लगता है कि फ़ंक्शन सही काम कर रहा है — यह [95]
वाली लिस्ट लौटाता है। लेकिन जब आप record_score(85)
को कॉल करते हैं, तो फ़ंक्शन [95, 85]
वाली लिस्ट लौटाता है। ऐसा लगता है जैसे फ़ंक्शन को पिछली बार की लिस्ट याद है।यह आपको सोचने पर मजबूर कर सकता है। अधिकांश प्रोग्रामिंग भाषाओं में, जब एक फ़ंक्शन समाप्त होता है, तो उसके सभी स्थानीय वेरिएबल्स (जैसे
score_list
) हटा दिए जाते हैं और भूल जाते हैं। अगली बार जब फ़ंक्शन कॉल होता है, तो वह नए सिरे से शुरू होता है।लेकिन Python में, जब एक म्यूटेबल ऑब्जेक्ट को डिफ़ॉल्ट आर्ग्युमेंट के रूप में उपयोग किया जाता है, तो व्यवहार अलग होता है। Python फ़ंक्शन के परिभाषित होने पर डिफ़ॉल्ट आर्ग्युमेंट को केवल एक बार बनाता है। इसलिए हर बार जब आप बिना लिस्ट प्रदान किए
record_score
को कॉल करते हैं, तो Python उसी लिस्ट का उपयोग करता है जिसे उसने पहली बार फ़ंक्शन को परिभाषित करते समय बनाया था। यदि आप उस लिस्ट को संशोधित करते हैं (जैसे स्कोर जोड़कर), तो अगली बार फ़ंक्शन कॉल होने पर वह संशोधन बना रहता है।इस प्रकार, हमारे फ़ंक्शन में
score_list
सभी उन फ़ंक्शन कॉल्स में साझा की जाती है जहाँ हम अपनी लिस्ट प्रदान नहीं करते हैं। यही कारण है कि हमारे उदाहरण में स्कोर्स इकट्ठे हो रहे हैं।यह तो हमने नहीं चाहा था! हम चाहते थे कि
record_score
को प्रत्येक कॉल एक खाली लिस्ट से शुरू हो, जब तक कि हम अपनी खुद की लिस्ट प्रदान न करें।इससे बचने के लिए, एक सामान्य तरीका यह है कि म्यूटेबल आर्ग्युमेंट्स के लिए डिफ़ॉल्ट मान के रूप में
None
का उपयोग किया जाए। फिर, फ़ंक्शन के अंदर, अगर आर्ग्युमेंट None
है तो आप एक नया म्यूटेबल ऑब्जेक्ट बना सकते हैं। यहां बताया गया है कि आप इस समस्या से बचने के लिए record_score
फ़ंक्शन को कैसे लिख सकते हैं:def record_score(new_score, score_list=None):
if score_list is None: # यदि कोई लिस्ट प्रदान नहीं की गई,
score_list = [] # एक नई लिस्ट बनाएं
score_list.append(new_score)
return score_list
print(record_score(95)) # [95]
print(record_score(85)) # [85]
इस सुधारित संस्करण में, हर बार जब आप अपनी लिस्ट प्रदान नहीं करते हैं, तो
record_score
एक नई लिस्ट बनाता है। इस तरह, स्कोर्स फ़ंक्शन कॉल्स के बीच साझा नहीं होते हैं।💡
तो, मुख्य बात यह है:
Python में म्यूटेबल डिफ़ॉल्ट आर्ग्युमेंट्स अप्रत्याशित व्यवहार का कारण बन सकते हैं क्योंकि वे केवल एक बार बनाए जाते हैं, और हर बार फ़ंक्शन कॉल होने पर वही ऑब्जेक्ट उपयोग होता है। यह शायद वह नहीं है जो आप चाहते हैं, खासकर जब आप उस म्यूटेबल ऑब्जेक्ट को संशोधित करते हैं। इस समस्या से बचने के लिए, आप डिफ़ॉल्ट मान के रूप में
None
का उपयोग कर सकते हैं और आवश्यकता पड़ने पर फ़ंक्शन में एक नया ऑब्जेक्ट बना सकते हैं।