2011-01-03 26 views
5

मैंने सोचा कि मैं आज रात तक पायथन जानता था। ऐसा कुछ करने का सही तरीका क्या है? कैसे मैं सही ढंग से सूची या शब्दकोश की एक प्रति बनाना होगा ताकि जब b बदल गया है a उसके साथ नहीं बदलता है b = a कदम के बजायपायथन वस्तुओं भ्रम: ए = बी, बी संशोधित करें और एक बदलाव!

a = ["one", "two", "three"] 
b = a # here I want a complete copy that when b is changed, has absolutely no effect on a 
b.append["four"] 
print a # a now has "four" in it 

मूल रूप से मैं चाहता हूँ पता करने के लिए,,: यहाँ मेरी कोड है?

+5

ठीक है, आप पाइथन को नहीं जानते हैं। या कम से कम आप इसका एक महत्वपूर्ण हिस्सा नहीं जानते हैं, कौन से चर हैं। SO या उदा। पर समान प्रश्न देखें http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables। – delnan

+5

@ डेलनान निष्पक्ष होने के लिए, यह उन लोगों के लिए असामान्य गड़बड़ी नहीं है जो पाइथन के लिए नए हैं, यह समझने के लिए कि वेरिएबल असाइनमेंट जिसमें सूचियां शामिल हैं, संदर्भों को निर्दिष्ट करती हैं, हालांकि दावा "मैंने सोचा था कि मुझे पाइथन पता था" यह इंगित करता है कि वे "नया" नहीं हैं:) –

उत्तर

11

आप जो अनुभव कर रहे हैं वह संदर्भों की अवधारणा है। अजगर में सभी वस्तुओं के लिए एक संदर्भ है और जब आप एक से दो नामों a और b असाइन करते हैं, इस a और b दोनों ही वस्तु की ओर इशारा करते का परिणाम है।

>>> a = range(3) 
>>> b = a      # same object 
>>> b.append(3) 
>>> a, b      # same contents 
([0, 1, 2, 3], [0, 1, 2, 3]) 

सूचियों के साथ, आप एक नकल एक और ab = a[:] का उपयोग करने का एक नई सूची b है कि बनाने के कर सकते हैं।

>>> a = range(3) 
>>> b = a[:]     # make b a new copy of a 
>>> b.append(3) 
>>> a, b      # a is left unchanged 
([0, 1, 2], [0, 1, 2, 3]) 

किसी भी वस्तु के लिए एक अधिक सामान्य समाधान के लिए, copy module का उपयोग करें। एक उथली प्रतिलिपि आपके द्वारा कॉपी की जा रही वस्तु के भीतर संग्रहीत संदर्भों की प्रतिलिपि बनायेगी, जबकि एक गहरी प्रतिलिपि सभी वस्तुओं की नई प्रतियों को दोबारा बनायेगी।

>>> a = [range(2), range(3)] 
>>> b = copy.copy(a)   # shallow copy of a, equivalent to a[:] 
>>> b[0] = range(4) 
>>> a, b      # setting an element of b leaves a unchanged 
([[0, 1], [0, 1, 2]], [[0, 1, 2, 3], [0, 1, 2]]) 
>>> b[1].append(3) 
>>> a, b      # modifying an element of b modifies the element in a 
([[0, 1], [0, 1, 2, 3]], [[0, 1, 2, 3], [0, 1, 2, 3]]) 

>>> a = [range(2), range(3)] 
>>> b = copy.deepcopy(a)  # deep recursive copy of a 
>>> b[1].append(3) 
>>> a, b      # modifying anything in b leaves a unchanged 
([[0, 1], [0, 1, 2]], [[0, 1], [0, 1, 2, 3]]) 
+0

एक गहरी प्रति क्या है और एक उथली प्रति क्या है। मैंने dict.copy .__ doc__ स्ट्रिंग को देखा है कि यह एक "उथला" प्रतिलिपि है। क्या फर्क पड़ता है? – james

+5

http: // stackoverflow देखें।कॉम/प्रश्न/184710/क्या-अंतर-अंतर-बीच-गहरे-प्रति-और-एक-उथले-प्रति – Sapph

+0

यह वास्तव में एक उथली प्रतिलिपि है, लेकिन अन्यथा सूची की प्रतिलिपि बनाने का सही तरीका है। – Keith

1

एक वस्तु को कॉपी करने का सही तरीका

from copy import copy 
a = [1, 2, 3] 
b = copy(a) 

सुंदर सरल है। वहाँ सूचियों के लिए शॉर्टकट है:

a = [1, 2, 3] 
b = a[:] 

वहाँ भी है deepcopy() आप वस्तुओं सूची के रूप में अच्छी तरह से में नकल करना चाहते हैं।

+0

गहरी प्रतिभा का उपयोग करने से सावधान रहें। यह आपके मेमोरी उपयोग को विस्फोट कर सकता है, और कभी-कभी "unpicklable ऑब्जेक्ट" की विचित्र त्रुटियां देता है। लगभग सभी उपयोग मामलों के लिए आपको * प्रतिलिपि * की आवश्यकता नहीं है, और अन्य मामलों के लिए, एक उथली प्रतिलिपि होगी। – bukzor

1

यहाँ सूची a की एक प्रतिलिपि बनाने के लिए 3 तरीके हैं:

उपयोग टुकड़ा अंकन:

copy_of_a = list(a) 

प्रति मॉड्यूल का उपयोग करें:

copy_of_a = a[:] 

सूची निर्माता का प्रयोग करें

from copy import copy 
copy_of_a = copy(a) 

ये सभी उथले प्रतियां हैं, जो आपके प्रश्न के लिए पर्याप्त हैं। उथले प्रतिलिपि और गहरी प्रति के बीच के अंतर के बारे में जानने के लिए documentation of the copy module पढ़ें।

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