python - सूची को क्लोन या कॉपी कैसे करें?




list copy clone (15)

पायथन में एक सूची क्लोन या कॉपी करने के विकल्प क्या हैं?

new_list = my_list का उपयोग करते समय my_list हर बार my_list संशोधित करता है।
ऐसा क्यों है?


Answers

चलो शुरुआत से शुरू करते हैं और इसे थोड़ा गहरा खोजते हैं:

तो मान लें कि आपके पास दो सूची हैं:

list_1=['01','98']
list_2=[['01','98']]

और हमें पहली सूची से शुरू होने वाली दोनों सूची कॉपी करना होगा:

तो सबसे पहले कॉपी की सामान्य विधि से आज़माएं:

copy=list_1

अब यदि आप सोच रहे हैं कि प्रतिलिपि सूची_1 की प्रतिलिपि बनाई गई है तो आप गलत हो सकते हैं, चलो इसे जांचें:

The id() function shows us that both variables point to the same list object, i.e. they share this object.
print(id(copy))
print(id(list_1))

उत्पादन:

4329485320
4329485320

आश्चर्य चकित ? ठीक है चलो इसे एक्सप्लोर करें:

इसलिए जैसा कि हम जानते हैं कि पाइथन एक चर में कुछ भी स्टोर नहीं करता है, वेरिएबल्स केवल ऑब्जेक्ट को संदर्भित कर रहे हैं और ऑब्जेक्ट मूल्य को स्टोर करते हैं। यहां ऑब्जेक्ट list लेकिन हमने उसी ऑब्जेक्ट के दो संदर्भ दो अलग-अलग चर नामों से बनाए हैं। तो दोनों चर एक ही वस्तु को इंगित कर रहे हैं:

इसलिए जब आप copy=list_1 करते हैं तो वास्तव में क्या कर रहा है:

यहां छवि सूची_1 में और प्रति दो चर नाम हैं लेकिन ऑब्जेक्ट दोनों चर के लिए समान है जो list

इसलिए यदि आप कॉपी की गई सूची को संशोधित करने का प्रयास करते हैं तो यह मूल सूची को भी संशोधित करेगा क्योंकि सूची केवल एक ही है, आप उस सूची को संशोधित करेंगे चाहे आप कॉपी की गई सूची से या मूल सूची से हों:

copy[0]="modify"

print(copy)
print(list_1)

उत्पादन:

['modify', '98']
['modify', '98']

तो यह मूल सूची में संशोधन किया गया:

तब समाधान क्या है?

उपाय :

अब सूची की प्रतिलिपि बनाने की दूसरी पायथन विधि पर जाएं:

copy_1=list_1[:]

अब यह विधि उस चीज़ को ठीक करती है जिसे हम पहले मुद्दे में सामना कर रहे थे चलो इसे जांचें:

print(id(copy_1))
print(id(list_1))

4338792136
4338791432

इसलिए हम अपनी दोनों सूचीओं को अलग-अलग आईडी देख सकते हैं और इसका मतलब है कि दोनों चर विभिन्न वस्तुओं को इंगित कर रहे हैं, इसलिए वास्तव में यहां क्या चल रहा है:

आइए अब सूची को संशोधित करने का प्रयास करें और देखते हैं कि क्या हमें अभी भी पिछली समस्या का सामना करना पड़ रहा है:

copy_1[0]="modify"

print(list_1)
print(copy_1)

आउटपुट:

['01', '98']
['modify', '98']

इसलिए जब आप देख सकते हैं कि यह मूल सूची को संशोधित नहीं कर रहा है, तो यह केवल कॉपी की गई सूची में संशोधित है, इसलिए हम इसके साथ ठीक हैं।

तो अब मुझे लगता है कि हम कर रहे हैं? प्रतीक्षा करें कि हमें दूसरी नेस्टेड सूची भी कॉपी करनी है, तो चलिए पाइथोनिक तरीके से प्रयास करें:

copy_2=list_2[:]

तो सूची_2 को किसी अन्य ऑब्जेक्ट का संदर्भ देना चाहिए जो सूची 2 की प्रति है, चलिए जांचें:

print(id((list_2)),id(copy_2))

हमें आउटपुट मिलता है:

4330403592 4330403528

अब हम मान सकते हैं कि दोनों सूचियां अलग-अलग ऑब्जेक्ट को इंगित कर रही हैं, इसलिए आइए इसे संशोधित करने का प्रयास करें और देखते हैं कि यह वही है जो हम चाहते हैं:

तो जब हम कोशिश करते हैं:

copy_2[0][1]="modify"

print(list_2,copy_2)

यह हमें आउटपुट देता है:

[['01', 'modify']] [['01', 'modify']]

अब, यह थोड़ा उलझन में है कि हम पाइथोनिक तरीके से इस्तेमाल करते हैं और फिर भी, हम एक ही मुद्दे का सामना कर रहे हैं।

आइए इसे समझें:

तो जब हम करते हैं:

copy_2=list_2[:]

हम वास्तव में केवल बाहरी सूची की प्रतिलिपि बना रहे हैं, न कि नेस्टेड सूची में, इसलिए नेस्टेड सूची दोनों सूची के लिए एक ही वस्तु है, चलिए जांचें:

print(id(copy_2[0]))
print(id(list_2[0]))

उत्पादन:

4329485832
4329485832

तो वास्तव में जब हम copy_2=list_2[:] यह होता है कि:

यह सूची की प्रति बनाता है लेकिन केवल बाहरी सूची प्रतिलिपि, नेस्टेड सूची प्रति नहीं, नेस्टेड सूची दोनों चर के लिए समान है, इसलिए यदि आप नेस्टेड सूची को संशोधित करने का प्रयास करते हैं तो यह मूल सूची को भी संशोधित करेगा क्योंकि नेस्टेड सूची ऑब्जेक्ट दोनों के लिए समान है नेस्टेड सूची।

तो समाधान क्या है?

समाधान deep copy

from copy import deepcopy
deep=deepcopy(list_2)

तो अब इसे जांचें:

print(id((list_2)),id(deep))

उत्पादन:

4322146056 4322148040

दोनों आईडी अलग हैं, अब आइस्टेड सूची आईडी की जांच करें:

print(id(deep[0]))
print(id(list_2[0]))

उत्पादन:

4322145992
4322145800

जैसा कि आप देख सकते हैं कि दोनों आईडी अलग हैं इसलिए हम मान सकते हैं कि दोनों नेस्टेड सूची अब अलग-अलग ऑब्जेक्ट को इंगित कर रही हैं।

तो जब आप deep=deepcopy(list_2) जो वास्तव में होता है:

तो दोनों नेस्टेड सूची अलग-अलग ऑब्जेक्ट को इंगित कर रही हैं और उनके पास अब नेस्टेड सूची की अलग-अलग प्रति है।

आइए अब नेस्टेड सूची को संशोधित करने का प्रयास करें और देखते हैं कि क्या यह पिछले मुद्दे को हल करता है या नहीं:

तो अगर हम करते हैं:

deep[0][1]="modify"
print(list_2,deep)

उत्पादन:

[['01', '98']] [['01', 'modify']]

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

यदि आपको मेरा विस्तृत उत्तर पसंद है, तो मुझे यह बताकर बताएं, अगर आपको कोई संदेह है तो इस जवाब को वास्तविकता दें, टिप्पणी करें :)


new_list = list(old_list)


वेरिएबल और वैल्यू वाले अन्य भाषाओं के विपरीत, पायथन का नाम और ऑब्जेक्ट है

यह कथन:

a = [1,2,3]

सूची (ऑब्जेक्ट) को एक नाम देने का मतलब है, और, यह:

b = a

बस एक ही ऑब्जेक्ट को a नया नाम b , इसलिए जब भी आप किसी के साथ कुछ करते हैं, ऑब्जेक्ट बदलता है और इसलिए b बदल जाता है।

वास्तव में एक प्रतिलिपि बनाने का एकमात्र तरीका एक नई वस्तु बनाना है जैसे कि पहले से ही अन्य उत्तरों ने कहा है।

आप here इसके बारे में और अधिक देख सकते हैं।


अन्य सभी योगदानकर्ताओं ने बहुत अच्छे उत्तर दिए, जो काम करते हैं जब आपके पास एक आयाम ( copy.deepcopy() ) सूची होती है, हालांकि अब तक बताई गई विधियों में से केवल copy.deepcopy() एक सूची क्लोन / कॉपी करने के लिए काम करता है और यह इंगित नहीं करता है नेस्टेड list ऑब्जेक्ट्स जब आप बहुआयामी, नेस्टेड सूचियों (सूचियों की सूची) के साथ काम कर रहे हैं। जबकि ने इसका जवाब अपने संदर्भ में दिया है, इस मुद्दे के लिए थोड़ा और अधिक संभवतः बिल्ट-इन्स का उपयोग करके एक कामकाज है जो deepcopy लिए एक तेज विकल्प साबित कर सकता है।

जबकि new_list = old_list[:] , copy.copy(old_list)' और old_list.copy() के लिए एकल-स्तरीय सूचियों के लिए काम करते हैं, वे old_list और old_list में old_list list ऑब्जेक्ट्स पर इंगित करने के लिए वापस new_list , और एक में परिवर्तन करते हैं list वस्तुओं में से दूसरे में कायम रखा जाता है।

संपादित करें: नई जानकारी प्रकाश में लाई गई

जैसा कि eval() का उपयोग करके और पीएम 2Ring दोनों द्वारा इंगित किया गया था , केवल एक बुरा विचार नहीं है, यह copy.deepcopy() से भी धीमा है।

इसका मतलब है कि बहुआयामी सूचियों के लिए, एकमात्र विकल्प copy.deepcopy() । ऐसा कहा जा रहा है कि, यह वास्तव में एक विकल्प नहीं है क्योंकि जब आप इसे मध्यम आकार के बहुआयामी सरणी पर उपयोग करने का प्रयास करते हैं तो प्रदर्शन दक्षिण में जाता है। मैंने 42x42 सरणी का उपयोग करने का समय निर्धारित करने की कोशिश की, जो कि बायोइनफॉरमैटिक्स अनुप्रयोगों के लिए अनदेखा नहीं था, और मैंने प्रतिक्रिया के लिए इंतजार छोड़ दिया और इस पोस्ट में अपना संपादन टाइप करना शुरू कर दिया।

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

जैसा कि अन्य ने कहा है, बहु-आयामी सूचियों के लिए copy मॉड्यूल और copy.deepcopy का उपयोग करके महत्वपूर्ण प्रदर्शन समस्याएं हो सकती हैंdeepcopy प्रतिलिपि के बिना बहुआयामी सूची की प्रतिलिपि बनाने का एक अलग तरीका काम करने की कोशिश कर रहा है, (मैं एक ऐसे पाठ्यक्रम के लिए समस्या पर काम कर रहा था जो क्रेडिट प्राप्त करने के लिए पूरे एल्गोरिदम चलाने के लिए केवल 5 सेकंड की अनुमति देता है), मैं एक तरह से आया नेस्टेड सूची की प्रतिलिपि बनाने के लिए अंतर्निहित कार्यों का उपयोग करने के लिए उन्हें एक-दूसरे पर या list ऑब्जेक्ट की सूची के बिना। मैंने पुराने सूची की एक लिंक बनाये बिना पुरानी सूची की प्रति नई सूची में कॉपी करने के लिए असाइनमेंट में eval() और repr() का उपयोग किया। यह रूप लेता है:

new_list = eval(repr(old_list))

असल में यह क्या करता है old_list को स्ट्रिंग के रूप में old_list करता है और फिर स्ट्रिंग का मूल्यांकन करता है जैसे कि यह ऑब्जेक्ट होता है जो स्ट्रिंग का प्रतिनिधित्व करता है। ऐसा करके, मूल list ऑब्जेक्ट का कोई लिंक नहीं बनाया गया है। एक नई list वस्तु बनाई गई है और प्रत्येक परिवर्तनीय बिंदु अपने स्वयं के स्वतंत्र वस्तु पर है। यहां 2 आयामी घोंसला वाली सूची का उपयोग करके एक उदाहरण दिया गया है।

old_list = [[0 for j in range(y)] for i in range(x)] # initialize (x,y) nested list

# assign a copy of old_list to new list without them pointing to the same list object
new_list = eval(repr(old_list)) 

# make a change to new_list 
for j in range(y):
    for i in range(x):
    new_list[i][j] += 1

यदि आप प्रत्येक सूची की सामग्री की जांच करते हैं, उदाहरण के लिए 4 से 3 सूची, पायथन वापस आ जाएंगे

>>> new_list

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

>>> old_list

[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

हालांकि यह संभवतः ऐसा करने के लिए कैननिकल या वाक्य रचनात्मक रूप से सही तरीका नहीं है, ऐसा लगता है कि यह अच्छी तरह से काम करता है। मैंने प्रदर्शन का परीक्षण नहीं किया है, लेकिन मुझे लगता है कि eval() और rep() deepcopy की तुलना में चलाने के लिए कम ओवरहेड होगा।


thing[:] प्रयोग करें thing[:]

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

पाइथन संस्करण से स्वतंत्र एक बहुत ही सरल दृष्टिकोण पहले से दिए गए उत्तरों में गायब था, जिसका आप अधिकतर समय उपयोग कर सकते हैं (कम से कम मैं करता हूं):

new_list = my_list * 1       #Solution 1 when you are not using nested lists

हालांकि, अगर my_list में अन्य कंटेनर हैं (उदाहरण के लिए नेस्टेड सूचियों के लिए) आपको प्रतिलिपि लाइब्रेरी से ऊपर दिए गए उत्तरों में सुझाए गए अन्य लोगों के रूप में गहरी प्रतिलिपि का उपयोग करना होगा। उदाहरण के लिए:

import copy
new_list = copy.deepcopy(my_list)   #Solution 2 when you are using nested lists

बोनस : यदि आप तत्वों का उपयोग नहीं करना चाहते हैं (उर्फ उथली प्रतिलिपि):

new_list = my_list[:]

आइए समाधान # 1 और समाधान # 2 के बीच अंतर को समझें

>>> a = range(5)
>>> b = a*1
>>> a,b
([0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
>>> a[2] = 55 
>>> a,b
([0, 1, 55, 3, 4], [0, 1, 2, 3, 4])

जैसा कि आप देख सकते हैं समाधान # 1 पूरी तरह से काम करता है जब हम नेस्टेड सूचियों का उपयोग नहीं कर रहे थे। आइए देखें कि क्या होगा जब हम नेस्टेड सूचियों में समाधान # 1 लागू करते हैं।

>>> from copy import deepcopy
>>> a = [range(i,i+4) for i in range(3)]
>>> a
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
>>> b = a*1
>>> c = deepcopy(a)
>>> for i in (a, b, c): print i   
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]
>>> a[2].append('99')
>>> for i in (a, b, c): print i   
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99]]   #Solution#1 didn't work in nested list
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]]       #Solution #2 - DeepCopy worked in nested list


यह मुझे आश्चर्यचकित करता है कि इसका अभी तक उल्लेख नहीं किया गया है, इसलिए पूर्णता के लिए ...

आप "स्प्लट ऑपरेटर" के साथ अनपॅकिंग सूची निष्पादित कर सकते हैं: * , जो आपकी सूची के तत्वों की प्रतिलिपि भी बनायेगा।

old_list = [1, 2, 3]

new_list = [*old_list]

new_list.append(4)
old_list == [1, 2, 3]
new_list == [1, 2, 3, 4]

इस विधि के स्पष्ट नकारात्मक पक्ष यह है कि यह केवल पायथन 3.5+ में उपलब्ध है।

समय के अनुसार, यह अन्य सामान्य तरीकों से बेहतर प्रदर्शन करने लगता है।

x = [random.random() for _ in range(1000)]

%timeit a = list(x)
%timeit a = x.copy()
%timeit a = x[:]

%timeit a = [*x]

#: 2.47 µs ± 38.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
#: 2.47 µs ± 54.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
#: 2.39 µs ± 58.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

#: 2.22 µs ± 43.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

फ़ेलिक्स ने पहले से ही एक उत्कृष्ट उत्तर प्रदान किया है, लेकिन मैंने सोचा कि मैं विभिन्न विधियों की गति तुलना करूंगा:

  1. 10.5 9 सेकंड (105.9US / itn) - copy.deepcopy(old_list)
  2. 10.16 सेकंड (101.6us / itn) - शुद्ध पायथन Copy() विधि गहराई के साथ कक्षाओं की प्रतिलिपि बनाएँ
  3. 1.488 सेकंड (14.88us / itn) - शुद्ध पायथन Copy() विधि कक्षाओं की प्रतिलिपि नहीं बना रही है (केवल डिक्ट्स / सूचियों / टुपल्स)
  4. 0.325 सेकंड (3.25us / itn) - for item in old_list: new_list.append(item)
  5. 0.217 सेकंड (2.17us / itn) - [i for i in old_list] (एक सूची समझ )
  6. 0.186 सेकंड (1.86us / itn) - copy.copy(old_list)
  7. 0.075 सेकंड (0.75US / itn) - list(old_list)
  8. 0.053 सेकंड (0.53us / itn) - new_list = []; new_list.extend(old_list) new_list = []; new_list.extend(old_list)
  9. 0.039 सेकंड (0.3 9स / इट्न) - old_list[:] सूची old_list[:] ( सूची स्लाइसिंग )

तो सबसे तेज़ सूची स्लाइसिंग है। लेकिन ध्यान रखें कि copy.copy() , list[:] और list(list) , copy.deepcopy() और पायथन संस्करण के विपरीत सूची में किसी सूचियों, शब्दकोशों और कक्षा के उदाहरणों की प्रतिलिपि नहीं है, इसलिए यदि मूल परिवर्तन , वे प्रतिलिपि सूची में भी बदले जाएंगे और इसके विपरीत।

(यहां कोई स्क्रिप्ट है अगर कोई दिलचस्पी लेता है या कोई समस्या उठाना चाहता है :)

from copy import deepcopy

class old_class:
    def __init__(self):
        self.blah = 'blah'

class new_class(object):
    def __init__(self):
        self.blah = 'blah'

dignore = {str: None, unicode: None, int: None, type(None): None}

def Copy(obj, use_deepcopy=True):
    t = type(obj)

    if t in (list, tuple):
        if t == tuple:
            # Convert to a list if a tuple to 
            # allow assigning to when copying
            is_tuple = True
            obj = list(obj)
        else: 
            # Otherwise just do a quick slice copy
            obj = obj[:]
            is_tuple = False

        # Copy each item recursively
        for x in xrange(len(obj)):
            if type(obj[x]) in dignore:
                continue
            obj[x] = Copy(obj[x], use_deepcopy)

        if is_tuple: 
            # Convert back into a tuple again
            obj = tuple(obj)

    elif t == dict: 
        # Use the fast shallow dict copy() method and copy any 
        # values which aren't immutable (like lists, dicts etc)
        obj = obj.copy()
        for k in obj:
            if type(obj[k]) in dignore:
                continue
            obj[k] = Copy(obj[k], use_deepcopy)

    elif t in dignore: 
        # Numeric or string/unicode? 
        # It's immutable, so ignore it!
        pass 

    elif use_deepcopy: 
        obj = deepcopy(obj)
    return obj

if __name__ == '__main__':
    import copy
    from time import time

    num_times = 100000
    L = [None, 'blah', 1, 543.4532, 
         ['foo'], ('bar',), {'blah': 'blah'},
         old_class(), new_class()]

    t = time()
    for i in xrange(num_times):
        Copy(L)
    print 'Custom Copy:', time()-t

    t = time()
    for i in xrange(num_times):
        Copy(L, use_deepcopy=False)
    print 'Custom Copy Only Copying Lists/Tuples/Dicts (no classes):', time()-t

    t = time()
    for i in xrange(num_times):
        copy.copy(L)
    print 'copy.copy:', time()-t

    t = time()
    for i in xrange(num_times):
        copy.deepcopy(L)
    print 'copy.deepcopy:', time()-t

    t = time()
    for i in xrange(num_times):
        L[:]
    print 'list slicing [:]:', time()-t

    t = time()
    for i in xrange(num_times):
        list(L)
    print 'list(L):', time()-t

    t = time()
    for i in xrange(num_times):
        [i for i in L]
    print 'list expression(L):', time()-t

    t = time()
    for i in xrange(num_times):
        a = []
        a.extend(L)
    print 'list extend:', time()-t

    t = time()
    for i in xrange(num_times):
        a = []
        for y in L:
            a.append(y)
    print 'list append:', time()-t

    t = time()
    for i in xrange(num_times):
        a = []
        a.extend(i for i in L)
    print 'generator expression extend:', time()-t

संपादित करें : बेंचमार्क में नई शैली, पुरानी शैली के वर्ग और डिब्बे जोड़े गए, और पायथन संस्करण को बहुत तेज बना दिया और सूची अभिव्यक्तियों और extend() सहित कुछ और तरीकों को जोड़ा।


पहले से ही कई जवाब हैं जो आपको बताते हैं कि उचित प्रतिलिपि कैसे बनाएं, लेकिन उनमें से कोई भी नहीं कहता कि आपकी मूल 'प्रति' विफल क्यों हुई।

पायथन वैरिएबल में मूल्यों को स्टोर नहीं करता है; यह वस्तुओं को नाम बांधता है। आपके मूल असाइनमेंट ने ऑब्जेक्ट को my_list द्वारा संदर्भित किया और इसे new_list में भी बाध्य कर दिया। इससे कोई फर्क नहीं पड़ता कि आप किस नाम का उपयोग करते हैं, अभी भी केवल एक सूची है, इसलिए इसका जिक्र करते समय किए गए परिवर्तन, क्योंकि my_list इसे my_list रूप में संदर्भित करते समय जारी new_list । इस प्रश्न के अन्य उत्तरों में से प्रत्येक आपको new_list से जुड़ने के लिए एक नई वस्तु बनाने के विभिन्न तरीकों को new_list

सूची का प्रत्येक तत्व किसी नाम की तरह कार्य करता है, जिसमें प्रत्येक तत्व गैर-विशेष रूप से किसी ऑब्जेक्ट को बांधता है। एक उथली प्रतिलिपि एक नई सूची बनाती है जिसका तत्व पहले की तरह एक ही वस्तु से बांधता है।

new_list = list(my_list)  # or my_list[:], but I prefer this syntax
# is simply a shorter way of:
new_list = [element for element in my_list]

अपनी सूची को एक कदम आगे कॉपी करने के लिए, अपनी ऑब्जेक्ट को संदर्भित करने वाली प्रत्येक ऑब्जेक्ट की प्रतिलिपि बनाएँ, और उन तत्व प्रतियों को एक नई सूची में बाध्य करें।

import copy  
# each element must have __copy__ defined for this...
new_list = [copy.copy(element) for element in my_list]

यह अभी तक एक गहरी प्रति नहीं है, क्योंकि किसी सूची का प्रत्येक तत्व अन्य ऑब्जेक्ट्स को संदर्भित कर सकता है, जैसे कि सूची इसके तत्वों से जुड़ी हुई है। सूची में प्रत्येक तत्व को दोबारा प्रतिलिपि बनाने के लिए, और फिर प्रत्येक तत्व द्वारा संदर्भित एक अन्य वस्तु, और इसी तरह: एक गहरी प्रतिलिपि करें।

import copy
# each element must have __deepcopy__ defined for this...
new_list = copy.deepcopy(my_list)

प्रतिलिपि में कोने के मामलों के बारे में अधिक जानकारी के लिए प्रलेखन देखें।


पायथन 3.6.0 समय

पाइथन 3.6.0 का उपयोग कर समय परिणाम यहां दिए गए हैं। ध्यान रखें कि ये समय एक दूसरे के सापेक्ष हैं, पूर्ण नहीं।

मैं केवल उथले प्रतियों को करने के लिए अटक गया, और कुछ नई विधियों को भी जोड़ा जो Python2 में संभव नहीं थे, जैसे list.copy() (पायथन 3 स्लाइस समकक्ष ) और *new_list, = list ( *new_list, = list ) *new_list, = list :

METHOD                  TIME TAKEN
b = a[:]                6.468942025996512   #Python2 winner
b = a.copy()            6.986593422974693   #Python3 "slice equivalent"
b = []; b.extend(a)     7.309216841997113
b = a[0:len(a)]         10.916740721993847
*b, = a                 11.046738261007704
b = list(a)             11.761539687984623
b = [i for i in a]      24.66165203397395
b = copy.copy(a)        30.853400873980718
b = []
for item in a:
  b.append(item)        48.19176080400939

हम पाइथन 3 list.copy() दृष्टिकोण की बढ़ी पठनीयता पर विचार करते हुए पुराने विजेता को अभी भी शीर्ष पर बाहर आते हैं, लेकिन वास्तव में बड़ी मात्रा में नहीं देख सकते हैं।

ध्यान दें कि ये विधियां सूचियों के अलावा किसी अन्य इनपुट के बराबर परिणाम नहीं देती हैं वे सभी टुकड़े करने योग्य वस्तुओं के लिए काम करते हैं, किसी भी काम के लिए कुछ काम करते हैं, लेकिन केवल copy.copy() किसी भी पायथन ऑब्जेक्ट के लिए काम करता है।

इच्छुक पार्टियों के लिए परीक्षण कोड यहां दिया गया है ( यहां से टेम्पलेट ):

import timeit

COUNT = 50000000
print("Array duplicating. Tests run", COUNT, "times")
setup = 'a = [0,1,2,3,4,5,6,7,8,9]; import copy'

print("b = list(a)\t\t", timeit.timeit(stmt='b = list(a)', setup=setup, number=COUNT))
print("b = copy.copy(a)\t\t", timeit.timeit(stmt='b = copy.copy(a)', setup=setup, number=COUNT))
print("b = a.copy()\t\t", timeit.timeit(stmt='b = a.copy()', setup=setup, number=COUNT))
print("b = a[:]\t\t", timeit.timeit(stmt='b = a[:]', setup=setup, number=COUNT))
print("b = a[0:len(a)]\t", timeit.timeit(stmt='b = a[0:len(a)]', setup=setup, number=COUNT))
print("*b, = a\t", timeit.timeit(stmt='*b, = a', setup=setup, number=COUNT))
print("b = []; b.extend(a)\t", timeit.timeit(stmt='b = []; b.extend(a)', setup=setup, number=COUNT))
print("b = []\nfor item in a: b.append(item)\t", timeit.timeit(stmt='b = []\nfor item in a:  b.append(item)', setup=setup, number=COUNT))
print("b = [i for i in a]\t", timeit.timeit(stmt='b = [i for i in a]', setup=setup, number=COUNT))

आप सूची () फ़ंक्शन में बुलेट का उपयोग कर सकते हैं:

newlist=list(oldlist)

मुझे लगता है कि यह कोड आपकी मदद करेगा।


new_list = my_list[:]

new_list = my_list इसे समझने का प्रयास करें। आइए मान लें कि my_list स्थान एक्स पर ढेर मेमोरी में है यानी my_list एक्स को इंगित कर रहा है। अब new_list = my_list असाइन करके आप एक्स को इंगित करने वाली नई_सूची दे रहे हैं। इसे उथले प्रतिलिपि के रूप में जाना जाता है।

अब यदि आप new_list = my_list[:] असाइन करते हैं new_list = my_list[:] आप मेरी mylist की प्रत्येक ऑब्जेक्ट को new_list में कॉपी कर रहे हैं। इसे दीप कॉपी के रूप में जाना जाता है।

अन्य तरीकों से आप यह कर सकते हैं:

  • new_list = list(old_list)
  • import copy new_list = copy.deepcopy(old_list)

new_list = my_list , आपके पास वास्तव में दो सूचियां नहीं हैं। असाइनमेंट सिर्फ सूची के संदर्भ की प्रतिलिपि बनाता है, वास्तविक सूची नहीं, इसलिए new_list और my_list दोनों असाइनमेंट के बाद एक ही सूची का संदर्भ लें।

वास्तव में सूची की प्रतिलिपि बनाने के लिए, आपके पास विभिन्न संभावनाएं हैं:

  • आप इसे टुकड़ा कर सकते हैं:

    new_list = old_list[:]
    

    इस बारे में एलेक्स मार्टेलि की राय (कम से कम 2007 में ) इस बात के बारे में है कि यह एक अजीब वाक्यविन्यास है और इसका उपयोग कभी भी समझ में नहीं आता है । ;) (उनकी राय में, अगला एक और पठनीय है)।

  • आप अंतर्निहित list() फ़ंक्शन का उपयोग कर सकते हैं:

    new_list = list(old_list)
    
  • आप जेनेरिक copy.copy() उपयोग कर सकते हैं:

    import copy
    new_list = copy.copy(old_list)
    

    यह list() से थोड़ा धीमा है क्योंकि इसे पहले old_list के डेटाटाइप को old_list

  • यदि सूची में ऑब्जेक्ट्स हैं और आप उन्हें कॉपी करना चाहते हैं, तो सामान्य copy.deepcopy() उपयोग करें:

    import copy
    new_list = copy.deepcopy(old_list)
    

    स्पष्ट रूप से सबसे धीमी और सबसे स्मृति-आवश्यकता विधि, लेकिन कभी-कभी अपरिहार्य।

उदाहरण:

import copy

class Foo(object):
    def __init__(self, val):
         self.val = val

    def __repr__(self):
        return str(self.val)

foo = Foo(1)

a = ['foo', foo]
b = a[:]
c = list(a)
d = copy.copy(a)
e = copy.deepcopy(a)

# edit orignal list and instance 
a.append('baz')
foo.val = 5

print('original: %r\n slice: %r\n list(): %r\n copy: %r\n deepcopy: %r'
      % (a, b, c, d, e))

परिणाम:

original: ['foo', 5, 'baz']
slice: ['foo', 5]
list(): ['foo', 5]
copy: ['foo', 5]
deepcopy: ['foo', 1]

मेरे लिए सबसे सरल लग रहा है:

>>> import numpy as np
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> print (np.concatenate(l))
[1 2 3 4 5 6 7 8 9]




python list copy clone