[python] सूचियों में अप्रत्याशित रूप से प्रतिबिंबित सूचियों की सूची की सूची



Answers

size = 3
matrix_surprise = [[0] * size] * size
matrix = [[0]*size for i in range(size)]

लाइव पायथन ट्यूटर विजुअलाइज करें

Question

मुझे पायथन में सूचियों की एक सूची बनाने की आवश्यकता है, इसलिए मैंने निम्नलिखित टाइप किया:

myList = [[1] * 4] * 3

सूची इस तरह दिखती है:

[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]  

तब मैंने सबसे निचले मूल्यों में से एक को बदल दिया:

myList[0][0] = 5

अब मेरी सूची इस तरह दिखती है:

[[5, 1, 1, 1], [5, 1, 1, 1], [5, 1, 1, 1]]  

जो मैं चाहता था या अपेक्षित नहीं था। क्या कोई बता सकता है कि क्या हो रहा है, और इसके आसपास कैसे जाना है?




इसे और अधिक वर्णनात्मक रूप से समझाने की कोशिश कर रहा है,

ऑपरेशन 1:

x = [[0, 0], [0, 0]]
print(type(x)) # <class 'list'>
print(x) # [[0, 0], [0, 0]]

x[0][0] = 1
print(x) # [[1, 0], [0, 0]]

ऑपरेशन 2:

y = [[0] * 2] * 2
print(type(y)) # <class 'list'>
print(y) # [[0, 0], [0, 0]]

y[0][0] = 1
print(y) # [[1, 0], [1, 0]]

नोटिस क्यों पहली सूची के पहले तत्व को संशोधित नहीं करता है प्रत्येक सूची के दूसरे तत्व को संशोधित नहीं करता है? ऐसा इसलिए है क्योंकि [0] * 2 वास्तव में दो संख्याओं की एक सूची है, और 0 का संदर्भ संशोधित नहीं किया जा सकता है।

यदि आप क्लोन प्रतियां बनाना चाहते हैं, तो ऑपरेशन 3 का प्रयास करें:

import copy
y = [0] * 2   
print(y)   # [0, 0]

y = [y, copy.deepcopy(y)]  
print(y) # [[0, 0], [0, 0]]

y[0][0] = 1
print(y) # [[1, 0], [0, 0]]

क्लोन प्रतियां बनाने के लिए एक और दिलचस्प तरीका, ऑपरेशन 4:

import copy
y = [0] * 2
print(y) # [0, 0]

y = [copy.deepcopy(y) for num in range(1,5)]
print(y) # [[0, 0], [0, 0], [0, 0], [0, 0]]

y[0][0] = 5
print(y) # [[5, 0], [0, 0], [0, 0], [0, 0]]



[[1] * 4] * 3

या और भी:

[[1, 1, 1, 1]] * 3

एक सूची बनाता है जो आंतरिक [1,1,1,1] 3 बार संदर्भित करता है - आंतरिक सूची की तीन प्रतियां नहीं, इसलिए जब भी आप सूची को संशोधित करते हैं (किसी भी स्थिति में), तो आप तीन बार परिवर्तन देखेंगे।

यह इस उदाहरण के समान है:

>>> inner = [1,1,1,1]
>>> outer = [inner]*3
>>> outer
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
>>> inner[0] = 5
>>> outer
[[5, 1, 1, 1], [5, 1, 1, 1], [5, 1, 1, 1]]

जहां यह शायद थोड़ा कम आश्चर्यजनक है।




मुझे लगता है कि हर कोई बता रहा है कि क्या हो रहा है। मैं इसे हल करने का एक तरीका सुझाता हूं:

myList = [[1 for i in range(4)] for j in range(3)]

myList[0][0] = 5

print myList

और फिर आपके पास है:

[[5, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]



सरल शब्दों में यह हो रहा है क्योंकि पाइथन में सब कुछ संदर्भ द्वारा काम करता है , इसलिए जब आप सूची की एक सूची बनाते हैं जिस तरह से आप मूल रूप से ऐसी समस्याओं का सामना करते हैं।

अपनी समस्या को हल करने के लिए आप इनमें से किसी एक को कर सकते हैं: 1. numpy.empty के लिए numpy सरणी दस्तावेज़ का उपयोग करें 2. सूची में शामिल होने पर सूची को शामिल करें। 3. यदि आप चाहें तो आप शब्दकोश का भी उपयोग कर सकते हैं




आइए हम आपके कोड को निम्न तरीके से दोबारा लिखें:

x = 1
y = [x]
z = y * 4

myList = [z] * 3

फिर यह सब कुछ और स्पष्ट करने के लिए निम्न कोड चलाएं। कोड क्या करता है मूल रूप से प्राप्त वस्तुओं के id एस मुद्रित करता है, जो

किसी ऑब्जेक्ट की "पहचान" वापस करें

और हमें उनकी पहचान करने में मदद करेगा और विश्लेषण करेगा कि क्या होता है:

print("myList:")
for i, subList in enumerate(myList):
    print("\t[{}]: {}".format(i, id(subList)))
    for j, elem in enumerate(subList):
        print("\t\t[{}]: {}".format(j, id(elem)))

और आपको निम्न आउटपुट मिलेगा:

x: 1
y: [1]
z: [1, 1, 1, 1]
myList:
    [0]: 4300763792
        [0]: 4298171528
        [1]: 4298171528
        [2]: 4298171528
        [3]: 4298171528
    [1]: 4300763792
        [0]: 4298171528
        [1]: 4298171528
        [2]: 4298171528
        [3]: 4298171528
    [2]: 4300763792
        [0]: 4298171528
        [1]: 4298171528
        [2]: 4298171528
        [3]: 4298171528

तो अब हम कदम-दर-चरण जाओ। आपके पास x जो 1 , और एक तत्व सूची y जिसमें x । आपका पहला कदम y * 4 जो आपको एक नई सूची z प्राप्त करेगा, जो मूल रूप से [x, x, x, x] , यानी यह एक नई सूची बनाता है जिसमें 4 तत्व होंगे, जो प्रारंभिक x ऑब्जेक्ट के संदर्भ हैं। नेट कदम बहुत समान है। आप मूल रूप से z * 3 , जो [[x, x, x, x]] * 3 और [[x, x, x, x], [x, x, x, x], [x, x, x, x]] , पहले चरण के लिए एक ही कारण के लिए।




Related