2012-01-05 21 views
90
द्वारा

एक उदाहरणअजगर सूची नहीं संदर्भ

a=['help', 'copyright', 'credits', 'license'] 
b=a 
b.append('XYZ') 
b 
['help', 'copyright', 'credits', 'license', 'XYZ'] 
a 
['help', 'copyright', 'credits', 'license', 'XYZ'] 

मैं इस सूची में मूल्य संलग्न करने के लिए 'बी' लेकिन सूची के मूल्य में 'एक' भी बदल दिया है चाहता था लेते हैं।
मुझे लगता है कि मुझे थोड़ा सा विचार नहीं है कि ऐसा क्यों है (पायथन संदर्भ द्वारा सूचियों को पास करता है)।
मेरा प्रश्न है "मैं इसे मूल्य से कैसे पास कर सकता हूं ताकि 'बी' में 'ए' में मूल्यों को बदलना न पड़े?"

उत्तर

137

रूप official Python FAQ में उत्तर दिया:

b = a[:] 
+3

मेरे लिए काम नहीं करता है। 'बी' में किए गए कोई भी परिवर्तन 'ए' में भी देखे जाते हैं। – Mannix

+1

@Mannix क्या आप [पूर्ण कोड] पोस्ट कर सकते हैं (https://stackoverflow.com/help/mcve) जो आपके पास एक नया प्रश्न में समस्या दिखाता है (यानी एक दावा विफल होना चाहिए)? सबसे अधिक संभावना है कि आप सूची को संशोधित नहीं कर रहे हैं, बल्कि इसके तत्व भी हैं। यदि आप एक नई सूची चाहते हैं जिसका तत्व प्रतियां हैं तो एक [गहरी प्रतिलिपि] (https://docs.python.org/dev/library/copy.html#copy.deepcopy) बनाएं। – phihag

5

बनाने के लिए एक सूची की एक प्रति ऐसा करते हैं: इसके अलावा

b = a[:] 
13

, आप कर सकते हैं:

b = list(a) 

यह काम करेंगे किसी अनुक्रम के लिए, यहां तक ​​कि वे इंडेक्सर्स और स्लाइस का समर्थन नहीं करते हैं ...

5

जब आप b = a कर आप बस है कि एक, का एक ही स्मृति के लिए एक और सूचक बनाने तुम क्यों , एक परिवर्तन भी करने के लिए संलग्न है।

आप एक की प्रतिलिपि बनाने की जरूरत है और कहा कि इस तरह किया जाता है:

b = a[:] 
106

एक सूची आप उपयोग कर सकते हैं कॉपी करने के लिए list(a) या a[:]। दोनों मामलों में एक नई वस्तु बनाई गई है।
इन दो तरीकों, तथापि, परिवर्तनशील वस्तुओं के संग्रह के साथ सीमाएं हैं के रूप में आंतरिक वस्तुओं उनके संदर्भ बरकरार रखें:

>>> a = [[1,2],[3],[4]] 

>>> b = a[:] 
>>> c = list(a) 

>>> c[0].append(9) 

>>> a 
[[1, 2, 9], [3], [4]] 
>>> c 
[[1, 2, 9], [3], [4]] 
>>> b 
[[1, 2, 9], [3], [4]] 
>>> 

आप अपने वस्तुओं की एक पूरी कॉपी चाहते हैं तो आप की जरूरत है copy.deepcopy

>>> from copy import deepcopy 
>>> a = [[1,2],[3],[4]] 

>>> b = a[:] 
>>> c = deepcopy(a) 

>>> c[0].append(9) 

>>> a 
[[1, 2], [3], [4]] 
>>> b 
[[1, 2], [3], [4]] 
>>> c 
[[1, 2, 9], [3], [4]] 
>>> 
+0

एक नियमित रूप से कॉपी और एक गहरी प्रतिलिपि के बीच क्या अंतर है? ऊपर क्या होता है? मुझे लगता है कि मेरे पास सामान्य समझ है, ऐसा लगता है कि दूसरी परत पर सेशन द्वारा सामना की जाने वाली एक ही समस्या है। यह आंतरिक रूप से कैसे काम करता है? – AsheKetchum

2

मैं पाया है कि हम विस्तार उपयोग कर सकते हैं() प्रतिलिपि()

a=['help', 'copyright', 'credits', 'license'] 
b = [] 
b.extend(a) 
b.append("XYZ") 
18

के समारोह को लागू करने के प्रदर्शन के संदर्भ में मेरी पसंदीदा जवाब होगा:

b.extend(a) 

चेक किस तरह से जुड़े विकल्प प्रदर्शन के मामले में एक दूसरे के साथ तुलना करें:

In [1]: import timeit 

In [2]: timeit.timeit('b.extend(a)', setup='b=[];a=range(0,10)', number=100000000) 
Out[2]: 9.623248100280762 

In [3]: timeit.timeit('b = a[:]', setup='b=[];a=range(0,10)', number=100000000) 
Out[3]: 10.84756088256836 

In [4]: timeit.timeit('b = list(a)', setup='b=[];a=range(0,10)', number=100000000) 
Out[4]: 21.46313500404358 

In [5]: timeit.timeit('b = [elem for elem in a]', setup='b=[];a=range(0,10)', number=100000000) 
Out[5]: 66.99795293807983 

In [6]: timeit.timeit('for elem in a: b.append(elem)', setup='b=[];a=range(0,10)', number=100000000) 
Out[6]: 67.9775960445404 

In [7]: timeit.timeit('b = deepcopy(a)', setup='from copy import deepcopy; b=[];a=range(0,10)', number=100000000) 
Out[7]: 1216.1108016967773 
+1

चर्चा में प्रदर्शन लाने के लिए धन्यवाद, इससे मुझे किस विधि का उपयोग करने का निर्णय लेने में मदद मिली। – Monkpit

+1

मुझे अभी आपका जवाब मिल गया है, इस उच्च गुणवत्ता वाले उत्तर के लिए धन्यवाद! पाइथन पर चर्चा करते समय अक्सर प्रदर्शन पर विचार नहीं किया जाता है और विशाल डेटा सेट के लिए यह अंतर बनाता है। – Artur

+0

मुझे यह जवाब पसंद है, हालांकि, यह सूची के मूल्यों से संबंधित नहीं है। जैसा कि जॉर्डन पाग्नि ने उल्लेख किया है, यदि आपकी सूची बहुआयामी है, सूचियों (और अधिक) के भीतर सूचियों में, तो एकमात्र समाधान जो काम करेगा, वह सबसे लंबा समय लेता है: बी = गहरी कॉपी (ए) –

5

आप एक आयामी सूची की प्रतिलिपि बनाना चाहते हैं, तो का उपयोग

b = a[:] 

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

b = [[a[x][y] for y in range(len(a[0]))] for x in range(len(a))] 
3

उसके जवाब में phihag से उल्लेख किया है,

b = a[:] 

अपने मामले के लिए काम करेंगे एक सूची टुकड़ा करने की क्रिया के बाद से सूची का एक नया स्मृति आईडी (जिसका अर्थ है बनाता है तुम अब कर रहे हैं तुम्हारी याद में एक ही वस्तु को संदर्भित और आप एक के लिए बनाने के परिवर्तन अन्य में नहीं दिखाई देंगे।)

हालांकि, वहाँ एक मामूली समस्या है। यदि आपकी सूची बहुआयामी है, सूचियों के भीतर सूचियों में, बस स्लाइसिंग इस समस्या को हल नहीं करेगी। उच्च आयामों में किए गए परिवर्तन, मूल सूची के भीतर अर्थात सूचियों, दोनों के बीच साझा किया जाएगा।

चिंता न करें, वहाँ एक समाधान है। मॉड्यूल कॉपी में निफ्टी कॉपीिंग तकनीक है जो इस समस्या का ख्याल रखती है।

from copy import deepcopy 

b = deepcopy(a) 

कोई फर्क नहीं पड़ता कि यह कैसे सूचियों के कई स्तर होते हैं एक नया स्मृति आईडी के साथ सूची की कॉपी जाएगा!

b = [] 
b[:] = a 

यह ख के लिए एक से सभी तत्वों को कॉपी करेंगे:

+0

ग्रेट उत्तर, जॉर्डन! धन्यवाद !!! क्या आप इसका कारण जानते हैं? – Felipe

1

मैं निम्नलिखित समाधान की सिफारिश करेंगे। प्रतिलिपि मूल्य प्रतिलिपि होगी, संदर्भ प्रति नहीं।

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