2013-07-17 10 views
11

मुझे यकीन है कि इसका उत्तर कहीं दिया गया है लेकिन मुझे यकीन नहीं था कि इसका वर्णन कैसे किया जाए।गुणा (*) अप्रत्याशित व्यवहार का उपयोग करते हुए उपन्यास उत्पन्न करना

lst = [[], [], []] 

मैंने सोचा कि मैं ऐसा करने से सभी चतुर किया जा रहा था:

चलो कहते हैं कि मैं, 3 खाली सूचियों ऐसी सूची बनाएं जिसमें इतने की तरह करना चाहते हैं

lst = [[]] * 3 

लेकिन मुझे पता चला के बाद, कुछ अजीब व्यवहार को डीबग करना, इसने की बजाय [[3], [3], [3]] बनाने के लिए, संपूर्ण सूची को अपडेट करने के लिए lst[0].append(3) कहें, एक सुस्तवादी को अद्यतन जोड़ना पड़ा।

हालांकि, अगर मैं

lst = [[] for i in range(3)] 

तो lst[1].append(5) कर के साथ इस सूची को प्रारंभ की उम्मीद देता [[], [5], []]

मेरा प्रश्न क्यों होता है है? यह ध्यान रखें कि अगर मैं

lst = [[]]*3 
lst[0] = [5] 
lst[0].append(3) 

करना तो सेल 0 की 'लिंकेज' टूट गया है और मैं [[5,3],[],[]] मिलता है, लेकिन अभी भी lst[1].append(0)[[5,3],[0],[0] का कारण बनता है दिलचस्प है।

मेरा सबसे अच्छा अनुमान यह है कि फॉर्म [[]]*x में गुणा का उपयोग करके पाइथन को एक सेल के संदर्भ को संग्रहीत करने का कारण बनता है ...?

+0

@RoadieRich लेकिन यहां के उत्तरों में आधिकारिक दस्तावेज़ीकरण के लिए बेहतर स्पष्टीकरण और लिंक हैं। –

+1

@ असीमबंसल: फिर उन उत्तरों को * अन्य * प्रश्न में शायद जोड़ा जाना चाहिए? –

+0

यह निश्चित रूप से एक डुप्लिकेट है। http://stackoverflow.com/questions/240178/unexpected-feature-in-a-python-list-of-lists और http://stackoverflow.com/questions/1605024/python-using-the-multiply-operator- टू-क्रू-ऑफ-ऑब्जेक्ट-इन-सूचियां और http://stackoverflow.com/questions/6688223/python-list-multiplication-3-makes-3-lists-which-mirror-each-other- कब? lq = 1 और अन्य मुझे अभी नहीं मिल रहा है। –

उत्तर

19

मेरा सबसे अच्छा अनुमान यह है कि फॉर्म [[]] * x में गुणा का उपयोग करके पाइथन को एक सेल के संदर्भ को स्टोर करने का कारण बनता है ...?

हां। और आप इसे स्वयं जांच सकते हैं

>>> lst = [[]] * 3 
>>> print [id(x) for x in lst] 
[11124864, 11124864, 11124864] 

इससे पता चलता है कि सभी तीन संदर्भ एक ही वस्तु का संदर्भ देते हैं। और ध्यान दें कि वास्तव में सही समझ में आता है कि यह होता है। यह सिर्फ मान की प्रतिलिपि बनाता है, और इस स्थिति में, मान संदर्भ हैं। और यही कारण है कि आप एक ही संदर्भ को तीन बार दोहराते हैं।

यह ध्यान रखें कि अगर मैं

lst = [[]]*3 
lst[0] = [5] 
lst[0].append(3) 

करना तो सेल 0 की 'लिंकेज' टूट गया है दिलचस्प है और मैं [[5,3],[],[]] मिलता है, लेकिन अभी भी lst[1].append(0)[[5,3],[0],[0] कारण बनता है।

आपने उस संदर्भ को बदल दिया है जो lst[0] पर है; यानी, आपने एक नया मानlst[0] असाइन किया है।लेकिन आपने अन्य तत्वों के मूल्य को नहीं बदला है, फिर भी वे उसी ऑब्जेक्ट को संदर्भित करते हैं जिसे उन्होंने संदर्भित किया था। और lst[1] और lst[2] अभी भी वही उदाहरण देखें, इसलिए lst[1] पर आइटम को जोड़ने से lst[2] का कारण यह भी दिखाई देता है।

यह क्लासिक गलती है जो लोग पॉइंटर्स और संदर्भों के साथ करते हैं। यहां सरल सादृश्य है। आपके पास कागज का एक टुकड़ा है। उस पर, आप किसी के घर का पता लिखते हैं। अब आप कागज के उस टुकड़े को ले लें, और दो बार फोटोकॉपी करें ताकि आप कागज़ के तीन टुकड़ों के साथ उसी पते के साथ समाप्त हो सकें। अब, पहले पेपर का टुकड़ा लें, उस पर लिखे गए पते को लिखें, और पर कोई नया पता लिखें घर। क्या पेपर के दूसरे दो टुकड़ों पर लिखा गया पता बदल गया? नहीं। बिल्कुल आपका कोड क्या था, हालांकि। यह क्यों अन्य दो आइटम नहीं बदलते हैं। इसके अलावा, कल्पना करें कि कागज के दूसरे टुकड़े पर अभी भी पते वाले घर के मालिक को उनके घर में एक ऐड-ऑन गेराज बनाता है। अब मैं आपसे पूछता हूं, क्या घर का पता तीसरा पेपर के टुकड़े पर एक एड-ऑन गेराज है? हां, ऐसा करता है, क्योंकि यह बिल्कुल वही घर जैसा है जिसका पता दूसरा पेपर का टुकड़ा लिखा गया है। यह आपके दूसरे कोड उदाहरण के बारे में सब कुछ बताता है।

: आपने पाइथन को "कॉपी कन्स्ट्रक्टर" का आह्वान करने की उम्मीद नहीं की थी? उलटी।

+1

+1। यह उपयोगी होगा। –

+0

'id (x)' के लिए धन्यवाद, और गेराज बिल्ड-ऑन पॉइंटर संपादन के लिए एक अच्छा उदाहरण है। –

5

ऐसा इसलिए है क्योंकि अनुक्रम गुणा केवल संदर्भों को दोहराता है। जब आप [[]] * 2 लिखते हैं, तो आप दो तत्वों के साथ एक नई सूची बनाते हैं, लेकिन इन दोनों तत्वों में समान ऑब्जेक्ट में स्मृति, अर्थात् खाली सूची है। इसलिए, एक में परिवर्तन दूसरे में परिलक्षित होता है।

>>> l1 = [[]] * 2 
>>> l2 = [[] for _ in xrange(2)] 
>>> l1[0] is l1[1] 
True 
>>> l2[0] is l2[1] 
False 
+0

मैंने "है" ऑपरेटर को आजमाने की कोशिश नहीं की, धन्यवाद! –

+0

@AdrianWan कोई समस्या नहीं, खुश मैं मदद कर सकता था। पाइथन डॉक्स के लिंक के लिए – arshajii

5

वे एक ही सूचियों संदर्भित कर रहे हैं: समझ, इसके विपरीत, एक नए, स्वतंत्र प्रत्येक यात्रा पर सूची बनाता है।

इसी तरह के सवाल here और here

और FAQ से कर रहे हैं: "। * प्रतियां पैदा नहीं करता, यह केवल मौजूदा वस्तुओं के लिए संदर्भ बनाता है"

+0

+1। –

1

आपका अनुमान है कि फ़ॉर्म में गुणा का उपयोग [[]] * x पाइथन को एक सेल के संदर्भ को स्टोर करने का कारण बनता है।

तो आप एक ही सूची में 3 संदर्भों की एक सूची के साथ समाप्त होते हैं।

1

मूल रूप से आपके पहले उदाहरण में क्या हो रहा है यह है कि एक ही सूची में एकाधिक संदर्भों के साथ एक सूची बनाई जा रही है। यहां एक ब्रेकडाउन है।

>>> a = [] 
>>> b = [a] 
>>> c = b * 3 # c now contains three references to a 
>>> d = [ a for _ in xrange(4) ] # and d contains four references to a 
>>> print c 
[[], [], []] 
>>> print d 
[[], [], [], []] 
>>> a.append(3) 
>>> print c 
[[3], [3], [3]] 
>>> print d 
[[3], [3], [3], [3]] 
>>> x = [[]] * 3 # shorthand equivalent to c 
>>> print x 
[[], [], []] 
>>> x[0].append(3) 
>>> print x 
[[3], [3], [3]] 

उपर्युक्त आपके पहले उदाहरण के बराबर है। अब जब प्रत्येक सूची को अपना चर दिया जाता है, उम्मीद है कि यह स्पष्ट क्यों है।c[0] is c[1]True के रूप में मूल्यांकन करेगा, क्योंकि दोनों अभिव्यक्ति एक ही वस्तु (a) का मूल्यांकन करती हैं।

आपका दूसरा उदाहरण कई अलग-अलग आंतरिक सूची वस्तुएं बनाता है।

>>> c = [[], [], []] # this line creates four different lists 
>>> d = [ [] for _ in xrange(3) ] # so does this line 
>>> c[0].append(4) 
>>> d[0].append(5) 
>>> print c 
[[4], [], []] 
>>> print d 
[[5], [], []] 
संबंधित मुद्दे