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


2543

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

उपयोग करते समय new_list = my_list, हर बार new_listबदलाव के लिए कोई भी संशोधन my_list। ऐसा क्यों है?

जवाबों:


3321

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

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

  • आप बिलिन list.copy()विधि का उपयोग कर सकते हैं (पायथन 3.3 के बाद से उपलब्ध):

    new_list = old_list.copy()
  • आप इसे स्लाइस कर सकते हैं:

    new_list = old_list[:]

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

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

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

    import copy
    new_list = copy.copy(old_list)
    

    यह थोड़ा धीमा है 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 'Foo({!r})'.format(self.val)

foo = Foo(1)

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

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

print('original: %r\nlist.copy(): %r\nslice: %r\nlist(): %r\ncopy: %r\ndeepcopy: %r'
      % (a, b, c, d, e, f))

परिणाम:

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

7
अगर मैं गलत नहीं हूँ: newlist = [*mylist]पायथन में भी एक संभावना है 3. newlist = list(mylist)हालांकि अधिक स्पष्ट है।
स्टीफन

9
एक अन्य व्यवसाय नई_लिस्ट = old_list * 1
aris

4
इन तरीकों में से कौन सी उथली प्रतिलिपि हैं और उनमें से कौन सी गहरी प्रति हैं?
इस्वर

4
@ ईश्वर: सभी लेकिन अंतिम एक उथली नकल करते हैं
फेलिक्स क्लिंग

3
@ इस्वर यह एक उथली प्रति है।
juanpa.arrivillaga

602

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

  1. 10.59 सेकंड (105.9us / आईटीएन) - copy.deepcopy(old_list)
  2. 10.16 सेकंड (101.6us / itn) - गहरी अजगर के Copy()साथ कक्षाओं की नकल करने वाली शुद्ध अजगर विधि
  3. 1.488 सेकंड (14.88us / itn) - शुद्ध अजगर Copy()विधि कक्षाओं की नकल नहीं (केवल डिक्सेस / लिस्ट / ट्यूपल्स)
  4. 0.325 सेकंड (3.25us / आईटीएन) - 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)
  9. 0.039 सेकंड (0.39us / itn) - 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

9
चूंकि आप बेंचमार्किंग कर रहे हैं, इसलिए संदर्भ बिंदु को शामिल करना मददगार हो सकता है। पूरी तरह से संकलित कोड के साथ पायथन 3.6 का उपयोग करके 2017 में ये आंकड़े अभी भी सटीक हैं? मैं नीचे जवाब नहीं दे रहा हूं ( stackoverflow.com/a/17810305/26219 ) पहले से ही इस जवाब पर सवाल उठाता है।
मार्क एडिंगटन

4
timeitमॉड्यूल का उपयोग करें । इसके अलावा, आप इस तरह के मनमाने माइक्रो बेंचमार्क से ज्यादा निष्कर्ष नहीं निकाल सकते हैं।
कोरी गोल्डबर्ग

3
यदि आप 3.5+ के लिए एक नया विकल्प शामिल करना चाहते हैं, [*old_list]तो यह लगभग बराबर होना चाहिए list(old_list), लेकिन चूंकि यह सिंटैक्स है, सामान्य फ़ंक्शन कॉल पथ नहीं है, इसलिए यह रनटाइम पर थोड़ा बचत करेगा (और इसके विपरीत old_list[:], जो टाइप नहीं करता है, [*old_list]किसी भी चलने योग्य पर काम करता है और एक list) पैदा करता है ।
शैडो रेंजर

3
@CoreyGoldberg थोड़े कम मनमाने माइक्रो-बेंचमार्क के लिए (उपयोग timeit, 100k के बजाय 50 मीटर रन) stackoverflow.com/a/43220129/3745896
नदी

1
@ShadowRanger [*old_list]वास्तव में लगभग किसी अन्य विधि से बेहतर प्रदर्शन करता है। (पिछली टिप्पणियों में जुड़ा हुआ मेरा उत्तर देखें)
नदी

150

मुझे बताया गया है कि Python 3.3+ मेथड को जोड़ताlist.copy() है, जो कि स्लाइसिंग जितना तेज़ होना चाहिए:

newlist = old_list.copy()


6
हाँ, और डॉक्स के अनुसार docs.python.org/3/library/stdtypes.html#mutable-fterence-types , (उतनी ही ) s.copy()की उथली प्रति बनाता है । ss[:]
साइबरएम

वास्तव में ऐसा लगता है कि वर्तमान में, python3.8, .copy()है थोड़ा तेजी से टुकड़ा करने की क्रिया से। नीचे देखें @AaronsHall जवाब।
प्रिय.जयस

125

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

पायथन 3 में, एक उथली प्रति के साथ बनाया जा सकता है:

a_copy = a_list.copy()

पायथन 2 और 3 में, आप मूल के पूर्ण स्लाइस के साथ एक उथले प्रति प्राप्त कर सकते हैं:

a_copy = a_list[:]

व्याख्या

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

उथली सूची कॉपी

उथली प्रतिलिपि केवल सूची को ही कॉपी करती है, जो सूची में वस्तुओं के संदर्भ में एक कंटेनर है। यदि स्वयं में समाहित वस्तुएं परिवर्तनशील हैं और एक को बदल दिया गया है, तो परिवर्तन दोनों सूचियों में परिलक्षित होगा।

पायथन 2 में ऐसा करने के अलग-अलग तरीके हैं और 3. पायथन 2 तरीके भी पायथन 3 में काम करेंगे।

अजगर २

पायथन 2 में, किसी सूची की उथली प्रतिलिपि बनाने का मुहावरेदार तरीका मूल के पूर्ण स्लाइस के साथ है:

a_copy = a_list[:]

आप सूची निर्माणकर्ता के माध्यम से सूची पास करके भी यही बात पूरी कर सकते हैं,

a_copy = list(a_list)

लेकिन निर्माणकर्ता का उपयोग करना कम कुशल है:

>>> timeit
>>> l = range(20)
>>> min(timeit.repeat(lambda: l[:]))
0.30504298210144043
>>> min(timeit.repeat(lambda: list(l)))
0.40698814392089844

अजगर ३

पायथन 3 में, सूचियों को list.copyविधि मिलती है :

a_copy = a_list.copy()

पायथन 3.5 में:

>>> import timeit
>>> l = list(range(20))
>>> min(timeit.repeat(lambda: l[:]))
0.38448613602668047
>>> min(timeit.repeat(lambda: list(l)))
0.6309100328944623
>>> min(timeit.repeat(lambda: l.copy()))
0.38122922903858125

दूसरा पॉइंटर बनाने से कॉपी नहीं बनती

New_list = my_list का उपयोग करना तब हर बार my_list परिवर्तन के लिए नए_सूची को संशोधित करता है। ऐसा क्यों है?

my_listसिर्फ एक नाम है जो स्मृति में वास्तविक सूची की ओर इशारा करता है। जब आप कहते हैं कि new_list = my_listआप प्रतिलिपि नहीं बना रहे हैं, तो आप स्मृति में उस मूल सूची में एक और नाम जोड़ रहे हैं। जब हम सूचियों की प्रतियां बनाते हैं तो हमारे पास समान मुद्दे हो सकते हैं।

>>> l = [[], [], []]
>>> l_copy = l[:]
>>> l_copy
[[], [], []]
>>> l_copy[0].append('foo')
>>> l_copy
[['foo'], [], []]
>>> l
[['foo'], [], []]

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

गहरी प्रतियां

किसी सूची की गहरी प्रतिलिपिdeepcopycopy बनाने के लिए, पायथन 2 या 3 में, मॉड्यूल में उपयोग करें :

import copy
a_deep_copy = copy.deepcopy(a_list)

यह प्रदर्शित करने के लिए कि यह हमें नई उप-सूची बनाने की अनुमति कैसे देता है:

>>> import copy
>>> l
[['foo'], [], []]
>>> l_deep_copy = copy.deepcopy(l)
>>> l_deep_copy[0].pop()
'foo'
>>> l_deep_copy
[[], [], []]
>>> l
[['foo'], [], []]

और इसलिए हम देखते हैं कि गहरी कॉपी की गई सूची मूल से पूरी तरह से अलग सूची है। आप अपना स्वयं का फ़ंक्शन रोल कर सकते हैं - लेकिन नहीं। आपको मानक लाइब्रेरी के डीकोकोपी फ़ंक्शन का उपयोग करके अन्यथा बग न बनाने की संभावना है।

उपयोग न करें eval

आप इसे डीपेकॉपी करने के तरीके के रूप में उपयोग कर सकते हैं, लेकिन ऐसा न करें:

problematic_deep_copy = eval(repr(a_list))
  1. यह खतरनाक है, खासकर यदि आप किसी ऐसे स्रोत से कुछ का मूल्यांकन कर रहे हैं जिस पर आपको भरोसा नहीं है।
  2. यह विश्वसनीय नहीं है, यदि आपके द्वारा कॉपी किए जा रहे सबलेमेंट में एक प्रतिनिधित्व नहीं है जो एक समान तत्व को पुन: पेश करने के लिए eval'd हो सकता है।
  3. यह भी कम प्रदर्शन है।

64 बिट पायथन 2.7 में:

>>> import timeit
>>> import copy
>>> l = range(10)
>>> min(timeit.repeat(lambda: copy.deepcopy(l)))
27.55826997756958
>>> min(timeit.repeat(lambda: eval(repr(l))))
29.04534101486206

64 बिट पायथन 3.5 पर:

>>> import timeit
>>> import copy
>>> l = list(range(10))
>>> min(timeit.repeat(lambda: copy.deepcopy(l)))
16.84255409205798
>>> min(timeit.repeat(lambda: eval(repr(l))))
34.813894678023644

1
यदि सूची 2 डी है तो आपको डीपकोपी की आवश्यकता नहीं है। यदि यह सूचियों की सूची है, और उन सूचियों के अंदर सूची नहीं है, तो आप लूप के लिए उपयोग कर सकते हैं। वर्तमान में, मैं उपयोग कर रहा हूं list_copy=[] for item in list: list_copy.append(copy(item))और यह बहुत तेज है।
जॉन लोके

53

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

अजगर चर में मूल्यों को संग्रहीत नहीं करता है; यह वस्तुओं को नाम बांधता है। आपके मूल असाइनमेंट द्वारा निर्दिष्ट ऑब्जेक्ट को ले लिया my_listऔर इसे भी बाध्य किया new_list। कोई फर्क नहीं पड़ता कि आप किस नाम का उपयोग करते हैं, अभी भी केवल एक सूची है, इसलिए जब इसका उल्लेख किया जाता है तो इसे my_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)

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



34

आइए शुरुआत से शुरू करें और इस सवाल का पता लगाएं।

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

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

और हमें दोनों सूचियों को कॉपी करना होगा, जो अब पहली सूची से शुरू होती है:

तो पहले copyहमारी मूल सूची में चर सेट करके कोशिश करते हैं list_1:

copy=list_1

अब अगर आप list_1 की कॉपी की सोच रहे हैं, तो आप गलत हैं। idसमारोह दो चर एक ही वस्तु को इंगित कर सकते हैं अगर हमें दिखा सकते हैं। चलो यह करके देखें:

print(id(copy))
print(id(list_1))

आउटपुट है:

4329485320
4329485320

दोनों चर एक ही तर्क हैं। क्या आप आश्चर्यचकित हैं?

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

जब आप करते हैं copy=list_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[:]

list_2किसी अन्य ऑब्जेक्ट का संदर्भ होना चाहिए जो की कॉपी है list_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[:]

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

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

आउटपुट है:

4329485832
4329485832

जब हम ऐसा करते हैं copy_2=list_2[:], तो ऐसा होता है:

यहां छवि विवरण दर्ज करें

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

उपाय क्या है? समाधान deepcopyकार्य है।

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']]

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


33

ऐसा करने के लिए पायथन का मुहावरा है newList = oldList[:]


33

पायथन 3.6 समय

यहां Python 3.6.8 का उपयोग करते हुए समय के परिणाम हैं। ध्यान रखें ये समय एक दूसरे के सापेक्ष हैं, निरपेक्ष नहीं।

मैं केवल उथली प्रतियों को करने के लिए अटक गया, और कुछ नए तरीकों को भी जोड़ा, जो कि Python2 में संभव नहीं थे, जैसे कि list.copy()(Python3 टुकड़ा समतुल्य ) और सूची के दो रूप अनपैकिंग ( *new_list, = listऔर new_list = [*list]):

METHOD                  TIME TAKEN
b = [*a]                2.75180600000021
b = a * 1               3.50215399999990
b = a[:]                3.78278899999986  # Python2 winner (see above)
b = a.copy()            4.20556500000020  # Python3 "slice equivalent" (see above)
b = []; b.extend(a)     4.68069800000012
b = a[0:len(a)]         6.84498999999959
*b, = a                 7.54031799999984
b = list(a)             7.75815899999997
b = [i for i in a]      18.4886440000000
b = copy.copy(a)        18.8254879999999
b = []
for item in a:
  b.append(item)        35.4729199999997

हम देख सकते हैं कि Python2 विजेता अभी भी अच्छा प्रदर्शन कर रहा है, लेकिन Python3 list.copy()को बाहर नहीं निकाल पाता है, विशेष रूप से बाद की बेहतर पठनीयता को देखते हुए।

डार्क हॉर्स अनपैकिंग और रीपैकिंग विधि ( b = [*a]) है, जो कच्चे स्लाइसिंग की तुलना में ~ 25% तेज है, और अन्य अनपैकिंग विधि ( *b, = a) की तुलना में दोगुनी है ।

b = a * 1 आश्चर्यजनक रूप से अच्छा भी करता है।

ध्यान दें कि ये विधियाँ सूचियों के अलावा किसी भी इनपुट के लिए समान परिणाम का उत्पादन नहीं करती हैं। वे सभी काम करने योग्य वस्तुओं के लिए काम करते हैं, किसी भी चलने योग्य के लिए कुछ काम करते हैं, लेकिन केवल 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", 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\t", timeit.timeit(stmt='b = a[0:len(a)]', setup=setup, number=COUNT))
print("*b, = a\t\t\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 = []; for 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))
print("b = [*a]\t\t", timeit.timeit(stmt='b = [*a]', setup=setup, number=COUNT))
print("b = a * 1\t\t", timeit.timeit(stmt='b = a * 1', setup=setup, number=COUNT))

1
3.8 पर अभी भी इसी तरह की कहानी की पुष्टि कर सकते हैं b=[*a]- यह करने का एक स्पष्ट तरीका;)।
सुपरशूट

19

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

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

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

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

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

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

जैसा कि दूसरों ने कहा है, मॉड्यूल का उपयोग करते हुए और बहुआयामी सूचियों के लिए महत्वपूर्ण प्रदर्शन मुद्दे हैं ।copycopy.deepcopy


5
यह हमेशा काम नहीं करेगा, क्योंकि इस बात की कोई गारंटी नहीं है कि स्ट्रिंग द्वारा लौटाए गए repr()ऑब्जेक्ट को फिर से बनाने के लिए पर्याप्त है। इसके अलावा, eval()अंतिम उपाय का एक उपकरण है; देखें Eval वास्तव में खतरनाक है जानकारी के लिए इतना अनुभवी नेड Batchelder द्वारा। इसलिए जब आप उपयोग की वकालत करते हैं eval()तो आपको वास्तव में उल्लेख करना चाहिए कि यह खतरनाक हो सकता है।
PM 2Ring

1
निष्पक्ष बिंदु। हालांकि मुझे लगता है कि बैटचेदर का कहना है कि eval()सामान्य रूप से पायथन में कार्य करना एक जोखिम है। यह इतना नहीं है कि आप कोड में फ़ंक्शन का उपयोग करते हैं या नहीं, लेकिन यह पायथन में और अपने आप में एक सुरक्षा छेद है। मेरे उदाहरण इसे प्रयोग नहीं कर रहा है एक समारोह है कि से इनपुट प्राप्त के साथ input(), sys.agrvया यहां तक कि एक पाठ फ़ाइल। यह एक बार एक रिक्त बहुआयामी सूची को आरम्भ करने की पंक्तियों के साथ अधिक है, और फिर लूप के प्रत्येक पुनरावृत्ति पर पुन: स्थापित करने के बजाय इसे लूप में कॉपी करने का एक तरीका है।
एएमआर

1
जैसा कि @AaronHall ने बताया है, उपयोग करने के लिए एक महत्वपूर्ण प्रदर्शन मुद्दा है new_list = eval(repr(old_list)), इसलिए इसके अलावा यह एक बुरा विचार है, यह संभवतः काम करने के लिए बहुत धीमा भी है।
AMR

12

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

आप "स्पैट ऑपरेटर" के साथ सूची अनपैकिंग कर सकते हैं: *जो आपकी सूची के तत्वों को भी कॉपी करेगा।

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
प्रतियां संशोधित करते समय यह विधि कैसे व्यवहार करती है?
not2qubit

2
@ not2qubit का मतलब है कि आप नई सूची के तत्वों को संपादित या संपादित कर रहे हैं। उदाहरण में old_listऔर new_listदो अलग-अलग सूचियां हैं, एक संपादन दूसरे को नहीं बदलेगा (जब तक कि आप सीधे तत्वों को स्वयं उत्परिवर्तित न करें (जैसे सूची की सूची), इनमें से कोई भी विधि गहरी प्रतियां नहीं हैं)।
SCB

7

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

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

7

ध्यान दें कि कुछ ऐसे मामले हैं जहाँ अगर आपने अपनी खुद की कस्टम क्लास को परिभाषित किया है और आप विशेषताओं को रखना चाहते हैं तो आपको विकल्प के बजाय copy.copy()या उपयोग करना चाहिए copy.deepcopy(), उदाहरण के लिए पायथन 3:

import copy

class MyList(list):
    pass

lst = MyList([1,2,3])

lst.name = 'custom list'

d = {
'original': lst,
'slicecopy' : lst[:],
'lstcopy' : lst.copy(),
'copycopy': copy.copy(lst),
'deepcopy': copy.deepcopy(lst)
}


for k,v in d.items():
    print('lst: {}'.format(k), end=', ')
    try:
        name = v.name
    except AttributeError:
        name = 'NA'
    print('name: {}'.format(name))

आउटपुट:

lst: original, name: custom list
lst: slicecopy, name: NA
lst: lstcopy, name: NA
lst: copycopy, name: custom list
lst: deepcopy, name: custom list

4
new_list = my_list[:]

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

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

दूसरा तरीका यह कर सकते हैं:

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

2

मैं कुछ अलग पोस्ट करना चाहता था तो कुछ अन्य उत्तर। भले ही यह सबसे अधिक समझने योग्य या सबसे तेज़ विकल्प न होने की संभावना है, लेकिन यह अंदर का एक दृश्य प्रदान करता है कि कितनी गहरी प्रतिलिपि काम करती है, साथ ही गहरी नकल के लिए एक और वैकल्पिक विकल्प है। यह वास्तव में मायने नहीं रखता है अगर मेरे फ़ंक्शन में बग हैं, क्योंकि इस बिंदु को प्रश्न के उत्तर जैसी वस्तुओं की प्रतिलिपि बनाने का एक तरीका दिखाना है, लेकिन यह भी एक बिंदु के रूप में इसका उपयोग यह समझाने के लिए है कि डीपॉस्कोपी इसके मूल में कैसे काम करता है।

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

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

एक बार जब आप जानते हैं कि, किसी भी संदर्भ के बिना किसी ऑब्जेक्ट को पूरी तरह से डुप्लिकेट करना बहुत आसान है। यहां बुनियादी डेटा-प्रकारों को डीपकोप करने के लिए एक फ़ंक्शन है (कस्टम कक्षाओं के लिए काम नहीं करेगा लेकिन आप हमेशा इसे जोड़ सकते हैं)

def deepcopy(x):
  immutables = (str, int, bool, float)
  mutables = (list, dict, tuple)
  if isinstance(x, immutables):
    return x
  elif isinstance(x, mutables):
    if isinstance(x, tuple):
      return tuple(deepcopy(list(x)))
    elif isinstance(x, list):
      return [deepcopy(y) for y in x]
    elif isinstance(x, dict):
      values = [deepcopy(y) for y in list(x.values())]
      keys = list(x.keys())
      return dict(zip(keys, values))

पाइथन की अपनी अंतर्निहित डीकोस्कोपी उस उदाहरण के आसपास आधारित है। एकमात्र अंतर यह है कि यह अन्य प्रकारों का समर्थन करता है, और एक नए डुप्लिकेट वर्ग में विशेषताओं को डुप्लिकेट करके उपयोगकर्ता-कक्षाओं का भी समर्थन करता है, और एक वस्तु के संदर्भ के साथ अनंत-पुनरावृत्ति को भी रोकता है जो पहले से ही मेमो सूची या शब्दकोश का उपयोग करके देखा जाता है। और यह वास्तव में गहरी प्रतियां बनाने के लिए है। इसके मूल में, एक गहरी प्रतिलिपि बनाना केवल उथली प्रतियां बनाना है। मुझे आशा है कि यह उत्तर प्रश्न में कुछ जोड़ता है।

उदाहरण

मान लें कि आपके पास यह सूची है: [1, 2, 3] । अपरिवर्तनीय संख्याओं को डुप्लिकेट नहीं किया जा सकता है, लेकिन दूसरी परत कर सकते हैं। आप एक सूची समझ का उपयोग करके इसे डुप्लिकेट कर सकते हैं: [1, 2, 3 में x के लिए x]

अब, कल्पना कीजिए कि आपके पास यह सूची है: [[1, 2], [3, 4], [5, 6]] । इस बार, आप एक फ़ंक्शन बनाना चाहते हैं, जो सूची की सभी परतों की गहरी प्रतिलिपि बनाने के लिए पुनरावृत्ति का उपयोग करता है। पिछली सूची की बजाय समझ:

[x for x in _list]

यह सूचियों के लिए एक नया प्रयोग करता है:

[deepcopy_list(x) for x in _list]

और deepcopy_list इस तरह दिखता है:

def deepcopy_list(x):
  if isinstance(x, (str, bool, float, int)):
    return x
  else:
    return [deepcopy_list(y) for y in x]

फिर अब आपके पास एक फ़ंक्शन है जो strs, bools, floast, ints और यहां तक ​​कि सूचियों की किसी भी सूची को पुनर्संरचना का उपयोग करके अनंत रूप से सूचीबद्ध कर सकता है। और वहां आपके पास है, डीपकोपिंग।

TLDR : डीपस्कोपी वस्तुओं को डुप्लिकेट करने के लिए पुनरावृत्ति का उपयोग करता है, और केवल वही अपरिवर्तनीय वस्तुओं को पहले की तरह वापस करता है, क्योंकि अपरिवर्तनीय वस्तुओं को डुप्लिकेट नहीं किया जा सकता है। हालाँकि, यह उत्परिवर्तित वस्तुओं की सबसे भीतरी परतों को तब तक गहरा करता है जब तक कि यह किसी वस्तु की सबसे बाहरी उत्परिवर्तित परत तक नहीं पहुँच जाती।


2

आईडी और जीसी के माध्यम से स्मृति में देखने के लिए एक मामूली व्यावहारिक दृष्टिकोण।

>>> b = a = ['hell', 'word']
>>> c = ['hell', 'word']

>>> id(a), id(b), id(c)
(4424020872, 4424020872, 4423979272) 
     |           |
      -----------

>>> id(a[0]), id(b[0]), id(c[0])
(4424018328, 4424018328, 4424018328) # all referring to same 'hell'
     |           |           |
      -----------------------

>>> id(a[0][0]), id(b[0][0]), id(c[0][0])
(4422785208, 4422785208, 4422785208) # all referring to same 'h'
     |           |           |
      -----------------------

>>> a[0] += 'o'
>>> a,b,c
(['hello', 'word'], ['hello', 'word'], ['hell', 'word'])  # b changed too
>>> id(a[0]), id(b[0]), id(c[0])
(4424018384, 4424018384, 4424018328) # augmented assignment changed a[0],b[0]
     |           |
      -----------

>>> b = a = ['hell', 'word']
>>> id(a[0]), id(b[0]), id(c[0])
(4424018328, 4424018328, 4424018328) # the same hell
     |           |           |
      -----------------------

>>> import gc
>>> gc.get_referrers(a[0]) 
[['hell', 'word'], ['hell', 'word']]  # one copy belong to a,b, the another for c
>>> gc.get_referrers(('hell'))
[['hell', 'word'], ['hell', 'word'], ('hell', None)] # ('hello', None) 

2

याद रखें कि पायथन जब आप करते हैं:

    list1 = ['apples','bananas','pineapples']
    list2 = list1

List2 वास्तविक सूची को संग्रहीत नहीं कर रहा है, लेकिन सूची 1 का संदर्भ है। तो जब आप list1 के लिए कुछ भी करते हैं, तो list2 भी बदल जाता है। सूची की मूल प्रतिलिपि ( नेस्टेड लोगों के लिए copy.copy(), सरल सूचियों के लिए ) बनाने के लिए कॉपी मॉड्यूल (डिफ़ॉल्ट रूप से, पाइप पर डाउनलोड नहीं copy.deepcopy()) का उपयोग करें। यह एक ऐसी प्रति बनाता है जो पहली सूची के साथ नहीं बदलती है।


0

Deepcopy विकल्प एकमात्र तरीका है जो मेरे लिए काम करता है:

from copy import deepcopy

a = [   [ list(range(1, 3)) for i in range(3) ]   ]
b = deepcopy(a)
b[0][1]=[3]
print('Deep:')
print(a)
print(b)
print('-----------------------------')
a = [   [ list(range(1, 3)) for i in range(3) ]   ]
b = a*1
b[0][1]=[3]
print('*1:')
print(a)
print(b)
print('-----------------------------')
a = [   [ list(range(1, 3)) for i in range(3) ] ]
b = a[:]
b[0][1]=[3]
print('Vector copy:')
print(a)
print(b)
print('-----------------------------')
a = [   [ list(range(1, 3)) for i in range(3) ]  ]
b = list(a)
b[0][1]=[3]
print('List copy:')
print(a)
print(b)
print('-----------------------------')
a = [   [ list(range(1, 3)) for i in range(3) ]  ]
b = a.copy()
b[0][1]=[3]
print('.copy():')
print(a)
print(b)
print('-----------------------------')
a = [   [ list(range(1, 3)) for i in range(3) ]  ]
b = a
b[0][1]=[3]
print('Shallow:')
print(a)
print(b)
print('-----------------------------')

के उत्पादन की ओर जाता है:

Deep:
[[[1, 2], [1, 2], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
*1:
[[[1, 2], [3], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
Vector copy:
[[[1, 2], [3], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
List copy:
[[[1, 2], [3], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
.copy():
[[[1, 2], [3], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
Shallow:
[[[1, 2], [3], [1, 2]]]
[[[1, 2], [3], [1, 2]]]
-----------------------------
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.