2012-02-23 7 views
6

सरल उदाहरण:पायथन में एक सूची इटरेटर को संशोधित करने की अनुमति नहीं है?

myList = [1, 2, 3, 4, 5] 
for obj in myList: 
    obj += 1 
print myList 

प्रिंट

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

जबकि:

myList = [1, 2, 3, 4, 5] 
for index in range(0,len(myList)): 
    myList[index] += 1 
print myList 

प्रिंट

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

निष्कर्ष:

  1. सूचियाँ वैश्विक सूची पहुंच सूची का उपयोग जगह में संशोधित किया जा सकता कर सकते हैं
  2. सूची आइटम कर सकते हैं नहीं इटरेटर वस्तु का उपयोग कर जगह में संशोधित किया जा

सभी उदाहरण कोड मैं पा सकते हैं का उपयोग करता है सूची सूची को संशोधित करने के लिए वैश्विक सूची एक्सेसर्स। क्या यह सूची पुनरावर्तक को संशोधित करना इतना बुरा है?

+0

'ए' क्या है ??? – DonCallisto

+0

जैसा कि है, यह कोड 'NameError' उत्पन्न करेगा क्योंकि' ए' परिभाषित नहीं किया गया है। – senderle

+0

आपके कोड उदाहरण खराब हैं। प्रिंट करने वाले पहले कहां से आते हैं? आपका प्रिंटिंग 'ए' जो मौजूद नहीं है और दो आउटपुट हैं। –

उत्तर

5

for obj in myList: में, हर चरण में, obj एक (उथले) myList में तत्व के प्रति है। तो obj पर परिवर्तन myList के तत्वों के लिए कुछ भी नहीं करता है।

यह सूची में पर्ल for my $obj (@myList) {}

+0

बिल्कुल, मैं अब समझता हूं। 'obj' सी ++ में एक पुनरावर्तक नहीं है, यह मूल रूप से वस्तु की एक प्रति है, जिसे अगले पुनरावृत्ति में अनदेखा किया जाता है। इस प्रकार, संशोधन केवल वैश्विक/प्रत्यक्ष सूची पहुंच का उपयोग करके किया जा सकता है। – RobW

+1

@RobW, 'obj' एक प्रति नहीं है, और यह उत्तर भ्रामक है। obj - पायथन में सभी चर की तरह - सी/सी ++ में एक सूचक की तरह है। [मेरे उत्तर] में संपादन देखें (http://stackoverflow.com/a/9414582/577088)। – senderle

+0

एडी वाईयू, जब आप "प्रतिलिपि" कहते हैं, तो मैं "तत्व की प्रतिलिपि" की बजाय "तत्व के पते की प्रति" कहता हूं। आप इसे स्पष्ट कर सकते हैं। – senderle

0

पहले उदाहरण में पूर्णांक को ओबीजे में कॉपी किया गया है जो 1. द्वारा बढ़ाया गया है सूची बदल नहीं है।

यदि आप कक्षा के उदाहरण का उपयोग करेंगे और उस पर संचालन करेंगे, तो यह बदला जाएगा।

1

आप उलझन में हैं। अपना पहला टुकड़ा पर विचार करें:

myList = [1, 2, 3, 4, 5] 
for obj in myList: 
    obj += 1 
print a 

obj सूची में जादुई सूचक किसी तरह का नहीं है। यह एक चर है जो किसी ऑब्जेक्ट का संदर्भ रखता है जो कि मेरी सूची में भी होता है। obj += 1obj में संग्रहीत मूल्य को बढ़ाने का प्रभाव डालता है। आपका कोड तब उस मूल्य के साथ कुछ भी नहीं करता है।

स्पष्ट होने के लिए: इस कोड उदाहरण में कोई प्रतियां नहीं हैं। obj एक चर है, जो सूची में एक वस्तु रखती है। बस इतना ही।

+0

यदि 'obj' सी ++ में एक पुनरावर्तक होगा, तो सूची ऑब्जेक्ट अपडेट किया जाएगा। लेकिन स्पष्ट रूप से, 'ओबीजे' एक प्रतिलिपि है और प्रत्येक पुनरावृत्ति के बाद परिवर्तनों को नजरअंदाज कर दिया जाता है। जाहिर है, पाइथन बाद वाला करता है, जो मेरा प्रश्न है। – RobW

+0

@RobW: मेरे बाद दोहराएं: इस कोड उदाहरण में कोई प्रतियां नहीं हैं। 'obj' एक चर है, जो सूची में एक वस्तु रखता है। बस इतना ही। – Marcin

6

कारण obj += 1 ऐसा नहीं करता है जो आप उम्मीद करते हैं कि यह कथन obj को जगह में संशोधित नहीं करता है। इसके बजाय, यह नए मान की गणना करने के लिए नए मान की गणना करता है, और परिवर्तनीय obj को मानता है। इसका मतलब है कि सूची की सामग्री अपरिवर्तित बनी हुई है।

सामान्य रूप से for obj in myList का उपयोग करते हुए इसे संशोधित करते समय सूची को संशोधित करने के लिए संभव है। उदाहरण के लिए:

myList = [[1], [2], [3], [4], [5]] 
for obj in myList: 
    obj[0] += 1 
print(myList) 

यह बाहर प्रिंट:

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

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

ध्यान दें कि एक भी एक सूची समझ का उपयोग कर पाश लिख सकते हैं:

myList = [val+1 for val in myList] 
+0

आपके उत्तर के लिए धन्यवाद। मैंने पहले से ही निष्कर्ष निकाला है कि 'ओबीजे' इटरेटर सी ++ में एक इटरेटर नहीं है, और ऑब्जेक्ट को संशोधित करने से सूची में बदलाव नहीं होता है। आप क्या कहते हैं कि 'ओबीजे' फिर से नई वस्तु के लिए बाध्य है जो अगले पुनरावृत्ति में खो जाएगा। स्पष्ट! – RobW

+0

महान जवाब! यह स्वीकार किए गए उत्तर के बारे में बात की गई 'उथली प्रतिलिपि' के बारे में नहीं है। – 8090PZ

0

संशोधन की अनुमति दी है साथ अलग है। आपके कोड उदाहरण arbove सुंदर glbled हैं ...

myList = [1, 2, 3, 4, 5] 
for index in range(0,len(myList)): 
    myList[index] += 1 
print myList 

यह काम करता है।

+0

है जो वास्तव में मैंने पोस्ट किया है और कुछ भी जवाब नहीं देता है। – RobW

4

मुझे लगता है कि आपने गलत समझा है कि "इटरेटर ऑब्जेक्ट" क्या है। एक for लूप एक पुनरावर्तक वस्तु नहीं है। सभी इरादों और मकसदों, एक पाश के लिए इस तरह के लिए:

myList = [0, 1, 2, 3, 4] 
for x in myList: 
    print x 

करता है (लेकिन और अधिक कुशलता से और कम verbosely):

i = 0 
while i < len(myList) 
    x = myList[i] 
    print x 
    i += 1 

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

जैसा कि अन्य ने देखा है, है जो इसे चालू करते समय सूची के मूल्य को बदलने के लिए संभव है।

for i, x in enumerate(myList): 
    myList[i] = some_func(x) 

अद्यतन: इस प्रकार है ऐसा करने के लिए एक सुंदर तरीका (लेकिन इसकी लंबाई को बदल नहीं है कि जहां मुसीबत में है!।) है यह भी समझना होगा कि कोई नकल पर चला जाता है के लिए महत्वपूर्ण है एक लूप में। उपर्युक्त उदाहरण में, i और x - पायथन में सभी चर की तरह - सी/सी ++ में पॉइंटर्स जैसे अधिक हैं। चूंकि लूप प्रगति करता है, objअंकmyList[0], myList[1], आदि में बदले में। और एक सी/सी ++ पॉइंटर की तरह, पॉइंटर बदलते समय ऑब्जेक्ट के गुणों को इंगित नहीं किया जाता है। लेकिन सी पॉइंटर की तरह, आप सीधे उस चीज़ को संशोधित कर सकते हैं, क्योंकि यह प्रतिलिपि नहीं है। सी में, यह dereferencing सूचक द्वारा किया जाता है; पायथन में, यह एक परिवर्तनीय वस्तु का उपयोग करके किया जाता है। यही कारण है कि NPE का उत्तर काम करता है। यदि i और x भी उथले प्रतियां थीं, तो वह ऐसा करना संभव नहीं होगा जो वह करता है।

कारण आप सीधे int नहीं बदल सकते, जिस तरह से आप list रों बदल सकते हैं (एनपीई के जवाब के रूप में) है यह है कि int रों परिवर्तनशील नहीं हैं। एक बार 5 ऑब्जेक्ट बनाया गया है, तो कुछ भी इसके मूल्य को बदल सकता है। यही कारण है कि 5 पर पॉइंटर के चारों ओर गुजरना पाइथन में सुरक्षित है - कोई दुष्प्रभाव नहीं हो सकता है, क्योंकि इस बात की ओर इशारा किया जाता है कि यह चीज अपरिवर्तनीय है।

+1

+1 – Fred

+0

के लिए +1 स्पष्ट रूप से, 'प्रिंट करें' प्रिंट 'मेरा लिस्ट' होना चाहिए, मैंने इसे ठीक किया है। पॉइंटर के लिए 'एन्युमेरेट' के लिए धन्यवाद, बहुत उपयोगी, सूची सूचकांक के लिए अपना कोड बनाए रखने से बचाता है! – RobW

+0

और भी पाइथोनिक और संक्षेप में होने के लिए, आप या तो [my_func (x) mylist में x के लिए 'या' मानचित्र (some_func, myList) 'कर सकते हैं, हालांकि वे प्रारंभिक सूची की प्रतियां बनाते हैं। –

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