2017-07-07 11 views
5

मेरे पास अजगर कार्यों में दायरे के बारे में एक प्रश्न है। मैंने एक उदाहरण शामिल किया है जो मेरे द्वारा जारी किए गए मुद्दे को प्रदर्शित करता है।पायथन फ़ंक्शन स्कोप

fun0 varible की सूची में पहले प्रवेश को पुनर्परिभाषित। यह परिवर्तन fun0 के बाहर परिलक्षित होता है, भले ही मैं fun0 से कोई मान वापस नहीं लौटाता।

fun1 चर पूरी तरह से पुनर्परिभाषित करता है, लेकिन परिवर्तन fun1 के बाहर प्रतिबिंबित नहीं होता है। इसी तरह, fun2 redefines c, और परिवर्तन fun2 के बाहर दिखाई नहीं देता है।

मेरा प्रश्न है, क्यों fun0 संशोधित करता है val3मुख्य समारोह में, जबकि fun1 और fun2val4 और val7 क्रमश: संशोधित नहीं करते हैं?

def fun0(a, b, c): 
    c[0] = a[0] + b[0] 
    return 

def fun1(a, b, c): 
    c = a[0] + b[0] 
    return 

def fun2(a, b, c): 
    c = a + b 
    return 

def main(): 
    val1 = ['one'] 
    val2 = ['two'] 
    val3 = [''] 
    fun0(val1, val2, val3) 
    print val3 

    val4 = [] 
    fun1(val1, val2, val4) 
    print val4 

    val5 = 1 
    val6 = 1 
    val7 = 0 
    fun2(val5, val6, val7) 
    print val7 
    return 

if __name__=='__main__': 
    main() 
+4

सूचियां उत्परिवर्तनीय हैं, आप उनके तत्वों को संशोधित कर सकते हैं और यह संदर्भ के साथ सभी को प्रभावित करता है। जब आप इसे फिर से असाइन करते हैं, तो आप एक नया संदर्भ बना रहे हैं। – byxor

+0

यह काफी अजीब बात है कि मैं कोड के अन्य टुकड़ों को "हर कोई" के रूप में कैसे संदर्भित करता हूं। हो सकता है कि मानवीय कोड इसे बेहतर समझने का मेरा तरीका है। – byxor

उत्तर

1

मेरा सवाल है, fun0 मुख्य समारोह में val3 को क्यों संशोधित करता है, जबकि fun1 और fun2 क्रमशः val4 और val7 को संशोधित नहीं करते हैं?

यह पाइथन तर्कों को पार करने के तरीके के कारण है।

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

हालांकि, जब आपने अपने कार्यों के अंदर c को फिर से सौंप दिया, तो आपने संदर्भों को संदर्भित किया cc को एक नया संदर्भ धारण और पुन: असाइन किया गया था।

+0

जहां तक ​​गुंजाइश है, मेरे उदाहरण के कार्यों में इनपुट पैरामीटर, स्थानीय और वैश्विक चर तक पहुंच है। यदि कोई तर्क उत्परिवर्तनीय है, तो कोई फ़ंक्शन इसके मानों को संदर्भ के अनुसार बदल सकता है, और बदले में, वे परिवर्तन फ़ंक्शन के दायरे से बाहर होते हैं (यदि मैं गलत हूं, या गलत हूं तो मुझे सही करें)। – shoe02

+0

हां, आपने जो कुछ भी कहा वह काफी सही है। एकमात्र टिप्पणी जो मैं करूँगा वह यह है कि चर डिफ़ॉल्ट रूप से वैश्विक नहीं हैं। [अधिक जानकारी के लिए यहां देखें] (https://stackoverflow.com/questions/10588317/python-function-global-variables)। –

+0

ठीक है, इसलिए जब मैं कोड की समीक्षा कर रहा हूं, तो मैं भी ध्यान रखूंगा कि कोई इनपुट पैरामीटर उत्परिवर्तनीय है या नहीं। आपके सहयोग के लिए धन्यवाद! – shoe02

2

इसे सूचियों और चरों को संग्रहीत करने के तरीके से करना है। आप किसी फ़ंक्शन के भीतर एक सूची को संशोधित कर सकते हैं क्योंकि वे उत्परिवर्तनीय वस्तुएं हैं। हालांकि, यदि आप c = a[0] + b[0] करते हैं, तो आप fun1 और fun2 के भीतर एक स्थानीय चर बना रहे हैं, जो फ़ंक्शन स्कोप के भीतर रहता है।

0

कैरी शिंदेल बिल्कुल सही है। इसके अलावा, यदि आप अद्यतन मानों को सहेजना चाहते हैं, तो यह है कि आप ऐसा करने के लिए अपना कोड कैसे बदल सकते हैं, मैंने प्रिंट स्टेटमेंट्स को बदल दिया क्योंकि मैंने इसका परीक्षण पायथन 3.6.1 में किया था। हालांकि अच्छा सवाल है।

def main(): 
    val1 = ['one'] 
    val2 = ['two'] 
    val3 = [''] 
    fun0(val1, val2, val3) 
    print(val3) 

    val4 = [] 
    val4 = fun1(val1, val2, val4) 
    print(val4) 

    val5 = 1 
    val6 = 1 
    val7 = 0 
    val7 = fun2(val5, val6, val7) 
    print(val7) 
    return 
1

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

0

जैसा कि पहले कहा गया था, सूचियां उत्परिवर्तनीय हैं। यदि आप एक सूची पास करते हैं और इसे संशोधित करते हैं, तो आप इसे हर जगह करते हैं। यह fun0 में सभी सूचियों के लिए लागू होता है।

fun2 में आप कोई सूचियां पास नहीं करते हैं और इसलिए c की गणना fun2 के भीतर की जाती है, लेकिन बाहर उपलब्ध नहीं है।

मुझे fun1 के बारे में निश्चित नहीं है, लेकिन मुझे लगता है कि आप c को एक नए चर के साथ ओवरराइट कर रहे हैं जो बाहर fun2 में उपलब्ध नहीं है।

संबंधित मुद्दे