2013-02-25 78 views
20

की बजाय उस फ़ंक्शन में वैश्विक की तरह काम करता है, मैं नीचे दिए गए व्यवहार से बहुत उलझन में हूं। मामले 1, 3, और 4 प्रदर्शन करते हैं जैसा कि मैं उम्मीद करता हूं, लेकिन मामला 2 नहीं है। क्यों मामला 2 वैश्विक स्तर पर शब्दकोश प्रविष्टि के मूल्य को बदलने की अनुमति देता है, भले ही शब्दकोश फ़ंक्शन द्वारा कभी वापस नहीं किया जाता है? फ़ंक्शन का उपयोग करने का एक मुख्य कारण यह है कि फ़ंक्शन में शेष कोड से सबकुछ अलग करना है, लेकिन यदि मैं फ़ंक्शन के अंदर समान वैरिएबल नामों का उपयोग करना चुनता हूं तो यह संभव नहीं लगता है। मैं इस समझ में था कि किसी फ़ंक्शन में स्पष्ट रूप से परिभाषित कुछ भी उस फ़ंक्शन के लिए स्थानीय है, लेकिन ऐसा लगता है कि शब्दकोश है जो फ़ंक्शन पर इनपुट के रूप में परिभाषित और पास किया गया है।पायथन शब्दकोश एक समारोह के लिए एक इनपुट के रूप में पारित किया गया है जो स्थानीय

Python 2.7.2+ (default, Oct 4 2011, 20:06:09) 
[GCC 4.6.1] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 

============= केस 1 ===============

>>> def testfun1(a): 
...  a=2 
... 
>>> a=0 
>>> testfun1(a) 
>>> a 
0 

====== ======= केस 2 ===============

>>> def testfun2(b): 
...  b['test']=2 
... 
>>> b={} 
>>> testfun2(b) 
>>> b 
{'test': 2} 

============= केस 3 ==== ===========

>>> def testfun3(): 
...  c=2 
... 
>>> c=0 
>>> testfun3() 
>>> c 
0 

============= प्रकरण 4 =============== (इस सवाल से समझाया: Global dictionaries don't need keyword global to modify them?)

>>> def testfun4(): 
...  d['test']=10 
... 
>>> d={} 
>>> testfun4() 
>>> d 
{'test': 10} 

उत्तर

35

Python's parameter passing acts a bit different than the languages you're probably used to। संदर्भ semantics द्वारा मूल्य और पास द्वारा स्पष्ट पास होने के बजाय, पायथन नाम से गुजर चुका है। आप अनिवार्य रूप से हमेशा ऑब्जेक्ट को पास कर रहे हैं, और ऑब्जेक्ट की व्यवहार्यता निर्धारित करती है कि इसे संशोधित किया जा सकता है या नहीं। सूचियां और डिब्बे म्यूटेबल ऑब्जेक्ट्स हैं। नंबर, स्ट्रिंग्स और टुपल्स नहीं हैं।

आप फ़ंक्शन में शब्दकोश को पास कर रहे हैं, प्रतिलिपि नहीं। इस प्रकार जब आप इसे संशोधित करते हैं, तो आप मूल प्रति को भी संशोधित कर रहे हैं।

इससे बचने के लिए, आपको पहले फ़ंक्शन को कॉल करने से पहले या फ़ंक्शन के भीतर से शब्दकोश को कॉपी करना चाहिए (dict फ़ंक्शन को पास करना चाहिए)।

+2

शब्दकोश को कॉपी करने के लिए कॉपी मॉड्यूल की प्रतिलिपि विधि का उपयोग करना चाहिए ** copy.deepcopy (डी) ** जो डी की गहरी प्रतिलिपि देता है। उथले बनाम गहरी प्रतिलिपि के बारे में अधिक जानकारी के लिए कृपया https://docs.python.org/2/library/copy.html –

+3

@PavanGupta देखें कि यह सब उस प्रतिलिपि पर निर्भर करता है जिस पर आप चाहते हैं। यदि आपके पास एक ऐसा नियम है जिसके मूल्य भी हैं, तो क्या आप उन डिक्टियों की प्रतियां बनाना चाहते हैं, या उन्हें इंगित करना चाहते हैं। यह नियम/प्रश्न बार-बार लागू होता है। – Darthfett

1

वैश्विक कीवर्ड केवल काम के लिए आवश्यक है (और संभावना del, मैं इसे करने की कोशिश कभी नहीं किया है)। ऑब्जेक्ट उत्परिवर्तन पूरी तरह मान्य हैं।

0

आपने फ़ंक्शन में dict ऑब्जेक्ट पारित किया है और इसे फ़ंक्शन के अंदर संशोधित किया है, इसलिए निश्चित रूप से इसे फ़ंक्शन रिटर्न के बाद संशोधित किया जाएगा। ऑब्जेक्ट की प्रतिलिपि बनाई गई नहीं है, इसलिए आप उसी ऑब्जेक्ट को संशोधित करते हैं जिसे आपने पारित किया है, और इस प्रश्न का नामकरण, समान नाम, स्कोप्स इत्यादि के साथ कुछ लेना देना नहीं है क्योंकि आपने ऑब्जेक्ट को स्पष्ट रूप से पारित किया है।

0

जब आप एक पूर्णांक या किसी स्ट्रिंग के लिए एक स्ट्रिंग जैसे मूल ऑब्जेक्ट को पास करते हैं, तो यदि आप इसे फ़ंक्शन के अंदर बदलते हैं तो फ़ंक्शन के बाहर संबंधित ऑब्जेक्ट में कुछ भी नहीं होता है क्योंकि जब आप किसी मूल ऑब्जेक्ट के साथ अग्रणी होते हैं, तो पाइथन इसे पास करता है मूल्य।

हालांकि, यदि आप किसी फ़ंक्शन में कोई शब्दकोश या सूची पास करते हैं तो वे संदर्भ द्वारा पारित होते हैं, जिसका अर्थ है कि आपके पास यह व्यवहार होगा: जैसा कि आपने देखा है, फ़ंक्शन के बाहर ऑब्जेक्ट बदल दिया गया है।

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

+0

उत्तर इंगित करके संशोधित किया जा सकता है कि तार अपरिवर्तनीय हैं और शब्दकोश परिवर्तनीय हैं। यह असली अंतर है। एक मूल वस्तु वास्तव में प्रति "परिभाषित" नहीं है। –

+0

@ स्कॉटलंडबर्ग लेकिन सी/सी ++ तारों जैसी अन्य भाषाओं में उत्परिवर्तनीय हैं; तथ्य यह है कि अजगर में तार अपरिवर्तनीय हैं (यानी मूल वस्तुएं) पाइथन भाषा की विशेषता है [वे एक सरणी या पात्रों की सूची - और सूचियां उत्परिवर्तनीय हो सकती हैं]। (अद्यतन उत्तर में अधिक जानकारी ...) –

+0

मैं आपसे सहमत हूं, इसलिए मैंने इसे स्पष्ट करने के लिए सुझाव दिया है। –