जेफिरनेट लोगो

5 सामान्य पायथन गॉचचास (और उनसे कैसे बचें) - केडनगेट्स

दिनांक:

5 आम अजगर पकड़ (और उनसे कैसे बचें)
लेखक द्वारा छवि
 

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

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

तो चलो शुरू करते है!

पायथन में, म्यूटेबल डिफॉल्ट्स सामान्य शार्प कॉर्नर हैं। जब भी आप किसी फ़ंक्शन को सूचियों या शब्दकोशों जैसी परिवर्तनशील वस्तुओं के साथ डिफ़ॉल्ट तर्क के रूप में परिभाषित करेंगे तो आपको अप्रत्याशित व्यवहार का सामना करना पड़ेगा। 

डिफ़ॉल्ट मान का मूल्यांकन केवल एक बार किया जाता है, जब फ़ंक्शन परिभाषित होता है, और हर बार फ़ंक्शन को कॉल करने पर नहीं. यदि आप फ़ंक्शन के भीतर डिफ़ॉल्ट तर्क को बदलते हैं तो इससे अप्रत्याशित व्यवहार हो सकता है।

आइए एक उदाहरण लेते हैं:

def add_to_cart(item, cart=[]):
    cart.append(item)
    return cart

 

इस उदाहरण में, add_to_cart एक फ़ंक्शन है जो एक आइटम लेता है और उसे एक सूची में जोड़ता है cart. का डिफ़ॉल्ट मान cart एक खाली सूची है. मतलब जोड़ने के लिए किसी आइटम के बिना फ़ंक्शन को कॉल करना एक खाली कार्ट लौटाता है। 

और यहां कुछ फ़ंक्शन कॉल हैं:

# User 1 adds items to their cart
user1_cart = add_to_cart("Apple")
print("User 1 Cart:", user1_cart)  

 

Output >>> ['Apple']

 

यह अपेक्षा के अनुरूप काम करता है। लेकिन अब क्या होगा?

# User 2 adds items to their cart
user2_cart = add_to_cart("Cookies")
print("User 2 Cart:", user2_cart) 

 

Output >>>

['Apple', 'Cookies'] # User 2 never added apples to their cart!

 

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

कैसे बचें

वर्कअराउंड के रूप में, आप सेट कर सकते हैं cart सेवा मेरे None और फ़ंक्शन के अंदर कार्ट को इस प्रकार प्रारंभ करें:

def add_to_cart(item, cart=None):
    if cart is None:
        cart = []
    cart.append(item)
    return cart

 

इसलिए अब प्रत्येक उपयोगकर्ता के पास एक अलग कार्ट है। 🙂

यदि आपको पायथन फ़ंक्शंस और फ़ंक्शन तर्कों पर पुनश्चर्या की आवश्यकता है, तो पढ़ें पायथन फ़ंक्शन तर्क: एक निश्चित मार्गदर्शिका.

पायथन के दायरे की विषमताओं के लिए स्वयं के एक ट्यूटोरियल की आवश्यकता होती है। लेकिन हम यहां ऐसी ही एक विचित्रता पर नजर डालेंगे।

निम्नलिखित स्निपेट देखें:

x = 10
squares = []
for x in range(5):
    squares.append(x ** 2)

print("Squares list:", squares)  

# x is accessible here and is the last value of the looping var
print("x after for loop:", x)

 

चर x 10 पर सेट है. लेकिन x लूपिंग वैरिएबल भी है। लेकिन हम मान लेंगे कि लूपिंग वेरिएबल का दायरा लूप ब्लॉक के लिए सीमित है, हाँ?

आइए आउटपुट देखें:

Output >>>

Squares list: [0, 1, 4, 9, 16]
x after for loop: 4

 

हम देखते है कि x अब 4 है, यह लूप में लिया जाने वाला अंतिम मान है, न कि 10 का प्रारंभिक मान जिस पर हमने इसे सेट किया है।

अब आइए देखें कि यदि हम फॉर लूप को कॉम्प्रिहेंशन एक्सप्रेशन से बदल दें तो क्या होता है:

x = 10
squares = [x ** 2 for x in range(5)]

print("Squares list:", squares)  

# x is 10 here
print("x after list comprehension:", x)

 

यहाँ, x 10 है, वह मान जिसे हम बोध अभिव्यक्ति से पहले निर्धारित करते हैं:

Output >>>

Squares list: [0, 1, 4, 9, 16]
x after list comprehension: 10

कैसे बचें

अप्रत्याशित व्यवहार से बचने के लिए: यदि आप लूप का उपयोग कर रहे हैं, तो सुनिश्चित करें कि आप लूपिंग वेरिएबल को किसी अन्य वेरिएबल के समान नाम न दें जिसे आप बाद में एक्सेस करना चाहते हैं।

पायथन में, हम इसका उपयोग करते हैं is वस्तु पहचान की जाँच के लिए कीवर्ड। मतलब यह जाँचता है कि क्या दो वेरिएबल मेमोरी में एक ही ऑब्जेक्ट को संदर्भित करते हैं। और समानता की जांच करने के लिए, हम इसका उपयोग करते हैं == ऑपरेटर। हाँ?

अब, Python REPL प्रारंभ करें और निम्नलिखित कोड चलाएँ:

>>> a = 7
>>> b = 7
>>> a == 7
True
>>> a is b
True

 

अब इसे चलाएँ:

>>> x = 280
>>> y = 280
>>> x == y
True
>>> x is y
False

 

रुको, ऐसा क्यों होता है? खैर, यह सीपीथॉन में "पूर्णांक कैशिंग" या "इंटर्निंग" के कारण है, जो पायथन का मानक कार्यान्वयन है।

सीपीथन पूर्णांक वस्तुओं को कैश करता है -5 से 256 की रेंज में. मतलब हर बार जब आप इस सीमा के भीतर एक पूर्णांक का उपयोग करते हैं, तो पायथन मेमोरी में उसी ऑब्जेक्ट का उपयोग करेगा। इसलिए, जब आप इसका उपयोग करके इस श्रेणी के भीतर दो पूर्णांकों की तुलना करते हैं is कीवर्ड, परिणाम है True वे क्योंकि स्मृति में उसी वस्तु को देखें.

इसीलिए a is b रिटर्न True. आप इसे प्रिंट करके भी सत्यापित कर सकते हैं id(a) और id(b).

हालाँकि, इस सीमा के बाहर के पूर्णांक कैश्ड नहीं होते हैं। और ऐसे पूर्णांकों की प्रत्येक घटना स्मृति में एक नई वस्तु बनाती है। 

इसलिए जब आप कैश्ड रेंज के बाहर दो पूर्णांकों की तुलना करते हैं is कीवर्ड (हाँ, x और y हमारे उदाहरण में दोनों को 280 पर सेट किया गया है), परिणाम है False क्योंकि वे वास्तव में स्मृति में दो अलग-अलग वस्तुएं हैं।

कैसे बचें

जब तक आप इसका उपयोग करने का प्रयास नहीं करते तब तक यह व्यवहार कोई समस्या नहीं होनी चाहिए is दो वस्तुओं की समानता की तुलना करने के लिए। इसलिए हमेशा इसका प्रयोग करें == ऑपरेटर यह जांचने के लिए कि क्या किन्हीं दो पायथन ऑब्जेक्ट का मान समान है।

यदि आप पायथन में अंतर्निहित डेटा संरचनाओं से परिचित हैं, तो आप जानते हैं कि टुपल्स हैं अडिग। तो तुम नही सकता उन्हें यथास्थान संशोधित करें. दूसरी ओर, सूचियाँ और शब्दकोश जैसी डेटा संरचनाएँ हैं परिवर्तनशील. मतलब आप कर सकते हैं उन्हें जगह में बदलें.

लेकिन उन टुपल्स के बारे में क्या जिनमें एक या अधिक परिवर्तनशील वस्तुएं होती हैं?

Python REPL प्रारंभ करना और यह सरल उदाहरण चलाना सहायक है:

>>> my_tuple = ([1,2],3,4)
>>> my_tuple[0].append(3)
>>> my_tuple
([1, 2, 3], 3, 4)

 

यहां, टुपल का पहला तत्व दो तत्वों वाली एक सूची है। हम पहली सूची में 3 जोड़ने का प्रयास करते हैं और यह ठीक काम करता है! खैर, क्या हमने सिर्फ एक टुपल को संशोधित किया है?

आइए अब सूची में दो और तत्व जोड़ने का प्रयास करें, लेकिन इस बार += ऑपरेटर का उपयोग करें:

>>> my_tuple[0] += [4,5]
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'tuple' object does not support item assignment

 

हां, आपको एक टाइप एरर मिलता है जो कहता है कि टपल ऑब्जेक्ट आइटम असाइनमेंट का समर्थन नहीं करता है। जो अपेक्षित है. लेकिन आइए टुपल की जाँच करें: 

>>> my_tuple
([1, 2, 3, 4, 5], 3, 4)

 

हम देखते हैं कि तत्व 4 और 5 को सूची में जोड़ा गया है! क्या प्रोग्राम ने केवल एक त्रुटि उत्पन्न की और उसी समय सफल हो गया?

वैसे += ऑपरेटर आंतरिक रूप से कॉल करके काम करता है __iadd__() वह विधि जो स्थान-स्थान पर जोड़ करती है और सूची को स्थान-स्थान पर संशोधित करती है। असाइनमेंट एक टाइप एरर अपवाद उठाता है, लेकिन सूची के अंत में तत्वों को जोड़ना पहले ही सफल हो चुका है। += शायद सबसे तेज़ कोना है!

कैसे बचें

अपने प्रोग्राम में ऐसी विचित्रताओं से बचने के लिए टुपल्स का उपयोग करने का प्रयास करें केवल अपरिवर्तनीय संग्रह के लिए. और जितना संभव हो परिवर्तनशील वस्तुओं को टुपल तत्वों के रूप में उपयोग करने से बचें।

परिवर्तनशीलता अब तक हमारी चर्चा में एक आवर्ती विषय रहा है। तो यहाँ इस ट्यूटोरियल को समाप्त करने के लिए एक और ट्यूटोरियल है।

कभी-कभी आपको सूचियों की स्वतंत्र प्रतियां बनाने की आवश्यकता हो सकती है। लेकिन क्या होता है जब आप इसके समान सिंटैक्स का उपयोग करके एक प्रतिलिपि बनाते हैं list2 = list1 जहां list1 क्या मूल सूची है?

यह एक उथली प्रतिलिपि है जो बनाई जाती है। इसलिए यह केवल सूची के मूल तत्वों के संदर्भों की प्रतिलिपि बनाता है। उथली प्रतिलिपि के माध्यम से तत्वों को संशोधित करने से प्रभाव पड़ेगा के छात्रों मूल सूची और उथली प्रति. 

आइए यह उदाहरण लें:

original_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

# Shallow copy of the original list
shallow_copy = original_list

# Modify the shallow copy
shallow_copy[0][0] = 100

# Print both the lists
print("Original List:", original_list)
print("Shallow Copy:", shallow_copy)

 

हम देखते हैं कि उथली प्रतिलिपि में परिवर्तन मूल सूची को भी प्रभावित करते हैं:

Output >>>

Original List: [[100, 2, 3], [4, 5, 6], [7, 8, 9]]
Shallow Copy: [[100, 2, 3], [4, 5, 6], [7, 8, 9]]

 

यहां, हम उथली प्रतिलिपि में पहली नेस्टेड सूची के पहले तत्व को संशोधित करते हैं: shallow_copy[0][0] = 100. लेकिन हम देखते हैं कि संशोधन मूल सूची और उथली प्रतिलिपि दोनों को प्रभावित करता है। 

कैसे बचें

इससे बचने के लिए, आप इस प्रकार एक गहरी प्रतिलिपि बना सकते हैं:

import copy

original_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

# Deep copy of the original list
deep_copy = copy.deepcopy(original_list)

# Modify an element of the deep copy
deep_copy[0][0] = 100

# Print both lists
print("Original List:", original_list)
print("Deep Copy:", deep_copy)

 

अब, डीप कॉपी में कोई भी संशोधन मूल सूची को अपरिवर्तित छोड़ देता है।

Output >>>

Original List: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Deep Copy: [[100, 2, 3], [4, 5, 6], [7, 8, 9]]

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

जैसे-जैसे आप पाइथॉन में लंबे समय तक कोडिंग करते रहेंगे—और भाषा को बेहतर ढंग से समझेंगे—आप शायद इनमें से कई का सामना करेंगे। तो, कोडिंग करते रहें, खोज करते रहें!

ओह, और यदि आप इस ट्यूटोरियल की अगली कड़ी पढ़ना चाहेंगे तो हमें टिप्पणियों में बताएं।
 
 

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

स्पॉट_आईएमजी

नवीनतम खुफिया

स्पॉट_आईएमजी