2016-10-09 3 views
5

मेरे पास निम्न कोड है, दूसरा व्यक्ति alist क्यों नहीं बदलता है जबकि दूसरा इसे बदलता है?पायथन: लूप के अंदर सूची और असाइन मूल्य की सूची लूप

alist = [[1,2], [3,4], [5,6]] 
for item in alist: 
    item = 1 
print(alist) 

alist = [[1,2], [3,4], [5,6]] 
for item in alist: 
    item = item.append(10) 
print(alist) 
+0

इस तरह इस्तेमाल होने पर पहला परिवर्तन: 'एलिस्ट में आइटम के लिए: alist [alist.index (item)] = 1' तो 'item' एक लूप में स्थानीय चर है, बाहर कुछ भी नहीं करें। पाइथन में प्रत्येक 'ब्लॉक के लिए – dsgdfg

उत्तर

5

इस चर का एक कुछ हद तक unintuitive behavor है। ऐसा इसलिए होता है क्योंकि, पायथन में, चर हमेशा मानों के संदर्भ होते हैं।

बक्से और टैग

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

एक ग्राफिक प्रतिनिधित्व कर सकते हैं। नीचे दी गई छवि alist = [[1,2], [3,4], [5,6]]

A list with three sublists

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

पहले पाश

जब आप निष्पादित for item in alist, आप सूची में से प्रत्येक मान लेने के लिए समय के अनुसार एक, चर item पर डाल दिया और इसमें कुछ आपरेशन कर दुभाषिया पूछ रहे हैं। पहले ऑपरेशन में, उदाहरण के लिए, हम इस नए स्कीमा है:

Now a variable points to a sublist

ध्यान दें कि हम item को sublist नकल नहीं है, इसके बजाय, हम item के माध्यम से यह इंगित। फिर, हम item = 1 निष्पादित करते हैं - लेकिन इसका क्या अर्थ है?इसका मतलब यह है कि हम मूल्य 1 को item बिंदु बना रहे हैं, बजाय sublist की ओर इशारा करते के:

item points to other value now

ध्यान दें कि वर्ष संदर्भ खो दिया है (यह लाल तीर है) और अब हम एक नया है। लेकिन हमने सिर्फ एक चर को एक सूची में बदल दिया - हमने सूची को स्वयं नहीं बदला।

फिर, हम दूसरे sublist को item अंक पाश की दूसरी यात्रा के लिए दर्ज करें, और अब:

item pointing to the second sublist

जब हम item = 1 निष्पादित, फिर से, हम सिर्फ चर बिंदु aonther मूल्य के लिए कर , सूची को बदले बिना:

enter image description here

अब, क्या होता है जब हम दूसरे लूप निष्पादित?

दूसरा पाश

दूसरे लूप पहले एक के रूप में शुरू होता है: हम item पहले sublist का उल्लेख करते हैं:

Now a variable points to a sublist

पहले अंतर यह है कि हम फोन item.append() है। append() एक विधि है, इसलिए यह उस ऑब्जेक्ट का मूल्य बदल सकता है जिसे वह कॉल कर रहा है। हम कहते हैं कि करने के लिए उपयोग के रूप में, हम मूल्य से 10 संलग्न करने के लिए इस मामले में वस्तु item द्वारा बताया करने के लिए एक संदेश भेज रहे हैं, आपरेशन नहीं चर item में किया जा रहा है, लेकिन सीधे वस्तु यह दर्शाता है में है!

A list has grown

हालांकि, हम केवल एक मूल्य सूची को संलग्न नहीं है: तो यहाँ item.append() बुला का परिणाम है! हम item.append() द्वारा दिए गए मान को भी असाइन करते हैं। यह item उपन्यास के संदर्भ को अलग करेगा, लेकिन यहां एक पकड़ है: append()None देता है।

enter image description here

None मूल्य

None एक मूल्य है कि प्रतिनिधित्व करता है, मूल रूप से, एक प्रासंगिक मूल्य की अनुपलब्धता है। जब कोई फ़ंक्शन None लौटाता है, तो यह कह रहा है, ज्यादातर समय, "मेरे पास आपको वापस देने के लिए कुछ भी प्रासंगिक नहीं है।" append() अपनी सूची सीधे बदलता है, इसलिए इसे वापस करने की आवश्यकता नहीं है।

यह महत्वपूर्ण है क्योंकि आप शायद मानते हैं कि item संलग्न सूची [1, 2, 10] पर इंगित करेगा, है ना? नहीं, अब यह None पर इंगित करता है। तो, आप नीचे दिए गए कोड की अपेक्षा करेंगे ...

alist = [[1,2], [3,4], [5,6]] 
for item in alist: 
    item = item.append(10) 
    print(item) 

कुछ इस तरह मुद्रित करने के लिए:

[1, 2, 10] 
[3, 4, 10] 
[5, 6, 10] 

लेकिन इस नहीं होता है। के रूप में हम टिप्पणी की, append() पद्धति को बदल कर सूचियों खुद को,

>>> alist = [[1,2], [3,4], [5,6]] 
>>> for item in alist: 
...  item = item.append(10) 
...  print(item) 
... 
None 
None 
None 

फिर भी: यह क्या होता है। इसलिए, item असाइनमेंट के बाद परिवर्तनीय बेकार था, अंतिम सूची संशोधित की गई है!

>>> print alist 
[[1, 2, 10], [3, 4, 10], [5, 6, 10]] 

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

>>> alist = [[1,2], [3,4], [5,6]] 
>>> for item in alist: 
...  item.append(10) 
...  print item 
... 
[1, 2, 10] 
[3, 4, 10] 
[5, 6, 10] 

यह काम करता है क्योंकि item अभी भी सूची को इंगित करेंगे।

निष्कर्ष

संदर्भ कुछ हद तक पहली बार में समझने के लिए, अकेले मास्टर जाने जटिल हैं। फिर भी, वे वास्तव में शक्तिशाली हैं और यदि आप उदाहरणों का पालन करते हैं तो सीखा जा सकता है। आपका उदाहरण थोड़ा जटिल है क्योंकि यहां और भी कुछ हो रहा है।

Python Tutor क्या हो रहा है यह समझने में आपकी सहायता कर सकता है, क्योंकि यह प्रत्येक चरण को ग्राफिक रूप से निष्पादित करता है। Check your own code running there!

1

संदर्भित the document:

के लिए लूप लक्ष्य सूची में चर (ओं) को कार्य करता है। यह के सुइट में किए गए उन सहित उन चर के सभी पिछले कार्य अधिलेखित कर देता है के लिए लूप:

for i in range(10): 
    print(i) 
    i = 5    # this will not affect the for-loop 
         # because i will be overwritten with the next 
         # index in the range 

तो अपने दूसरे उदाहरण समान है:

alist = [[1,2], [3,4], [5,6]] 
for item in alist: 
    item.append(10) # this statement modifies each item in alist 
         # , which is what item the variable "points to" 
print(alist) 

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

2

क्या आप भूल गए हैं कि list.append() सूची को वापस नहीं लौटाता है लेकिन वास्तव में सूची में बदलाव को संशोधित करता है?

item = 1 अपेक्षित है। शेष लूप के लिए, आइटम अब 1 है, और मूल रूप से यह सूची नहीं थी। यह पुन: असाइन नहीं करेगा कि item क्या है, यह लूप के लिए नहीं है।

हालांकि, अपने दूसरे पाश में, अब आप item = None बताए रहे हैं, संलग्न समारोह कुछ भी वापस नहीं करता है क्योंकि लेकिन यह जगह में सूची में आइटम जोड़ देती है:

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

इस प्रकार, अपने कोड मूल रूप से है कह रही है "मेरी मुख्य सूची में प्रत्येक उपन्यास के माध्यम से जाएं और 10 इसमें संलग्न करें"।

0

जब आप लिखना

for item in alist: 

आप वास्तव में item चर में liast में प्रत्येक आइटम की एक प्रतिलिपि बना रहे हैं तथा आप नहीं हैं item के लिए एक संदर्भ हो रही।

हालांकि, append यथा-स्थान सूची बदलता है और एक मूल्य वापस नहीं करता है, और यही कारण है कि आप मूल्यों None (करने के लिए बदल हो रही है काम की वजह से है - यदि आप इसे हटाने के स्थान पर कार्य appending मिलेगा ठीक)।

+0

' कोई प्रतिलिपि नहीं बनाता है, यानी प्रत्येक पुनरावृत्ति में 'alist' के प्रत्येक सदस्य को' आइटम 'अंक। – SuB

2

= ऑपरेटर .append का उपयोग करके दूसरे कोड में कोई बदलाव नहीं करता है, alist में परिवर्तन का कारण बनता है। दूसरे कोड में तीसरी पंक्ति के रूप में निम्न पंक्ति का प्रयोग करें। item=1 द्वारा

item.append(10) 

किसी अन्य वस्तु के लिए सबसे पहले कोड item बिंदु में, तो alist परिवर्तन नहीं करता है: आप एक ही परिणाम देखेंगे। दूसरे कोड में आप विधि को कॉल करके alist पर परिवर्तन करते हैं।

4

पहला उदाहरण item में सूची alist में प्रत्येक तत्व के लिए बाध्य है, और फिर itemपलटाव पूर्णांक 1 है। इस सूची के तत्व नहीं बदलता है - यह महज int वस्तु 1 को rebinds नाम item

सूची तत्व (अपने आप में एक सूची)

दूसरे उदाहरण में append() द्वारा उत्परिवर्तित है। item अभी भी उप-सूची के लिए बाध्य है इसलिए item.append() उप-सूची को म्यूट करता है।

2

यह अजगर में सूचक चर है।

पहला उदाहरण:

for item in alist: 
    item = 1 

प्रत्येक आइटम alist में प्रत्येक _item की ओर इशारा करते है, लेकिन अचानक आप आइटम मूल्य बदलने के लिए, नहीं alist में _item का मूल्य, alist करने के लिए एक परिणाम कुछ भी नहीं परिवर्तन के रूप में की

दूसरे उदाहरण:

for item in alist: 
    item = item.append(10) 

प्रत्येक आइटम alist में प्रत्येक _item की ओर इशारा करते है और फिर आप आइटम का एक ही स्मृति स्थान साझा करने के लिए कुछ संलग्न _item, alist में _item के परिणाम मान के रूप में बदल दिया गया है और alist भी बदल दिया गया है।

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