2010-05-28 15 views
6

मैं कुछ विवरणों के बारे में सोच रहा हूं कि कैसे ... पायथन में काम करता है।क्यों पाइथन का 'इन ... इन' कामों की सूची बनाम मूल्यों की सूची पर अलग-अलग काम करता है?

मेरी समझ for var in iterable प्रत्येक पुनरावृत्ति पर एक चर, विविध, वर्तमान मूल्य के लिए बाध्य बनाता है। इसलिए, यदि आप for c in cows; c = cows[whatever] करते हैं, लेकिन लूप के भीतर सी बदलना मूल मान को प्रभावित नहीं करता है। हालांकि, यदि आप एक शब्दकोश कुंजी को मान निर्दिष्ट कर रहे हैं तो ऐसा लगता है कि यह अलग-अलग काम करता है।

cows=[0,1,2,3,4,5] 
for c in cows: 
    c+=2 

#cows is now the same - [0,1,2,3,4,5] 

cows=[{'cow':0},{'cow':1},{'cow':2},{'cow':3},{'cow':4},{'cow':5}] 
for c in cows: 
    c['cow']+=2 

# cows is now [{'cow': 2}, {'cow': 3}, {'cow': 4}, {'cow': 5}, {'cow': 6}, {'cow': 7} 
#so, it's changed the original, unlike the previous example 

मुझे लगता है कि कोई भी पहला उदाहरण काम करने के लिए गणना का उपयोग कर सकता है, लेकिन यह एक अलग कहानी है, मुझे लगता है।

cows=[0,1,2,3,4,5] 
for i,c in enumerate(cows): 
    cows[i]+=1 

# cows is now [1, 2, 3, 4, 5, 6] 

यह दूसरे उदाहरण में मूल सूची मानों को क्यों प्रभावित करता है लेकिन पहले नहीं?

[संपादित करें]

उत्तर के लिए धन्यवाद। मैं इसे PHP बिंदु दृश्य से देख रहा था, जहां आप संदर्भ में & प्रतीक का उपयोग कर सकते हैं यह निर्दिष्ट करने के लिए कि क्या आप किसी संदर्भ या पुनरावर्तनीय की प्रति पर काम कर रहे हैं या नहीं। अब मैं देखता हूं कि वास्तविक अंतर एक मूलभूत विवरण है कि पाइथन अपरिवर्तनीय वस्तुओं के बारे में कैसे काम करता है।

उत्तर

4

for ... in ... के साथ ऐसा करने के लिए कुछ भी नहीं है। प्रत्येक उदाहरण में for c in cows: से c = cows[3] (और अगली पंक्ति को समर्पित करें) से अपना कोड बदलें और प्रभाव देखें।

आपके पहले उदाहरण में, सूची तत्व int ऑब्जेक्ट्स हैं; वे अपरिवर्तनीय हैं। दूसरे उदाहरण में, वे dict वस्तुओं हैं, जो mutable हैं।

+0

के लिए +1 मैंने आपका जवाब स्वीकार कर लिया क्योंकि 'अपरिवर्तनीय' जादू शब्द है। मुझे अब याद है कि इनट्स पाइथन में अलग-अलग वस्तुएं हैं, इसलिए यह उस नाम को पहले उदाहरण में किसी अन्य ऑब्जेक्ट पर रीबंड कर रहा था, और उसी ऑब्जेक्ट को दूसरे में संशोधित कर रहा था। – JAL

3

नाम लूप में आपके नाम के रूप में नाम असाइनमेंट करना केवल नाम को पुनर्निर्मित करता है। आपके पास दूसरी लूप में एक आइटम एग्जिगमेंट करना मौजूदा ऑब्जेक्ट को संशोधित करता है।

4

c दोनों मामलों में एक अस्थायी, डिस्पोजेबल चर है। (ध्यान रखें कि पायथन में, सभी चर केवल संदर्भ हैं, जो वे प्रतिनिधित्व करते हैं और विभिन्न वस्तुओं के लिए रिबाउंड करने में सक्षम हैं। पाइथन इस संबंध में कुछ अन्य भाषाओं की तुलना में अधिक संगत है।)

आपकी सूची उदाहरण में , प्रत्येक पुनरावृत्ति c को एक पूर्णांक से दूसरे में पुनर्निर्मित करता है, मूल सूची अपरिवर्तित छोड़ देता है।

आपके ताना उदाहरण में, प्रत्येक पुनरावृत्ति उस नियम तक पहुंच जाती है जिस पर c अस्थायी रूप से बाध्य है, उस ताना के सदस्यों में से एक को एक पूर्ण पूर्णांक में पुन: बाध्य कर रहा है।

दोनों मामलों में, c को लूप के अंत में अनदेखा किया जाता है, लेकिन चूंकि आपने दूसरे मामले में c के अलावा डेटा संरचना बदल दी है, तो आप लूप होने पर परिवर्तनों को देखते हैं।

5

यह वास्तव में अलग-अलग अभिनय नहीं कर रहा है। एक चर बदलना एक चर के गुण को बदलने के समान नहीं है। आप निम्न उदाहरण में एक ही बात देखेंगे:

a = 1 
b = a 
b = 2 

यहाँ एक अभी भी है 1. ख भिन्न मान सौंपा गया था और अब एक

a = {"hello": 1} 
b = a 
b["hello"] = 2 

यहाँ a["hello] रिटर्न 2 रूप में ही है इसके बजाय 1. b अभी भी वही मान है क्योंकि हमने b पर कुछ भी असाइन नहीं किया है, और इस प्रकार ba जैसा ही है।हम 2 करने के लिए b की संपत्ति ["hello"] बदल गया है और a और b के बाद से कर रहे हैं एक ही चर a["hello"] भी 2

16

यह चित्र क्या संदर्भ प्रत्येक चरण में c द्वारा आयोजित करने के लिए होता है में मदद करता है:

[ 0, 1, 2, 3, 4, 5 ] 
^
    | 
    c 

ग सूची में पहले तत्व को इंगित करने वाला एक संदर्भ रखता है। जब आप c += 2 कर (यानी, c = c + 2, अस्थायी चर c एक नया मान पुन: असाइन किया गया है। इस नए मूल्य, अब 2 है, और c इस नए मूल्य के लिए पलटाव है। मूल सूची अकेला छोड़ दिया जाता है।

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

    c -> 2 

शब्दकोश मामले में, यहाँ क्या c पहले यात्रा के दौरान करने के लिए बाध्य कर रहा है:।

[ {'cow':0}, {'cow':1}, {'cow':2}, {'cow':3}, {'cow':4}, {'cow':5} ] 
    ^
    | 
    c 

यहाँ, शब्दकोश वस्तु {'cow':0} को c अंक जब आप ऐसा करेंगे c['cow'] += 2 (यानी, c['cow'] = c['cow'] + 2), शब्दकोश वस्तु स्वयं बदल जाती है, क्योंकि c किसी असंबंधित वस्तु के लिए रीबाउंड नहीं है। यही है, c अभी भी उस प्रथम शब्दकोश वस्तु को इंगित करता है।

[ {'cow':2}, {'cow':1}, {'cow':2}, {'cow':3}, {'cow':4}, {'cow':5} ] 
    ^
    | 
    c 
+0

+1, बहुत अच्छा जवाब! :) – jathanism

+0

चित्रकारी प्रतिनिधित्व – Davy8

1

दूसरे उदाहरण में, आप एक सूची शब्दकोश वस्तुओं की है। c लूप स्कोप के अंदर संशोधित शब्दकोश वस्तु का संदर्भ देता है।

1

पाशन के बावजूद, आप ध्यान दें कि है:

some_var = some_object 

वस्तु some_object के नाम some_var बांधता है। some_var द्वारा संदर्भित पिछली वस्तु (यदि कोई है) अनबाउंड है।

some_var[some_index] = some_object 

some_var को बाध्य/अनबाइंड नहीं करता है;

some_var.__setitem__(some_index, some_object) 

जाहिर है, some_var अब भी वही इंडेक्स करने योग्य (एक दृश्य या एक मानचित्रण) को इंगित करता है के रूप में पहले वस्तु, जो सिर्फ संशोधित किया गया है: यह निम्नलिखित के लिए बस वाक्यात्मक चीनी है।

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