उथले कॉपी, डीपकोपी और सामान्य असाइनमेंट ऑपरेशन में क्या अंतर है?


210
import copy

a = "deepak"
b = 1, 2, 3, 4
c = [1, 2, 3, 4]
d = {1: 10, 2: 20, 3: 30}

a1 = copy.copy(a)
b1 = copy.copy(b)
c1 = copy.copy(c)
d1 = copy.copy(d)


print("immutable - id(a)==id(a1)", id(a) == id(a1))
print("immutable - id(b)==id(b1)", id(b) == id(b1))
print("mutable - id(c)==id(c1)", id(c) == id(c1))
print("mutable - id(d)==id(d1)", id(d) == id(d1))

मुझे निम्नलिखित परिणाम मिले:

immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False

अगर मैं गहरी प्रदर्शन करता हूं:

a1 = copy.deepcopy(a)
b1 = copy.deepcopy(b)
c1 = copy.deepcopy(c)
d1 = copy.deepcopy(d)

परिणाम समान हैं:

immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) False
mutable - id(d)==id(d1) False

यदि मैं असाइनमेंट ऑपरेशन पर काम करता हूं:

a1 = a
b1 = b
c1 = c
d1 = d

फिर परिणाम हैं:

immutable - id(a)==id(a1) True
immutable - id(b)==id(b1) True
mutable - id(c)==id(c1) True
mutable - id(d)==id(d1) True

क्या कोई समझा सकता है कि प्रतियों के बीच वास्तव में क्या अंतर है? क्या यह उत्परिवर्तनीय और अपरिवर्तनीय वस्तुओं से संबंधित है? यदि हां, तो क्या आप इसे मुझे समझा सकते हैं?

जवाबों:


364

सामान्य असाइनमेंट ऑपरेशन, मौजूदा ऑब्जेक्ट की ओर नए चर को इंगित करेगा। डॉक्स उथले और गहरी प्रतियां के बीच अंतर की व्याख्या:

उथली और गहरी नकल के बीच का अंतर केवल यौगिक वस्तुओं के लिए प्रासंगिक है (ऐसी वस्तुएं जिनमें अन्य वस्तुएं हैं, जैसे सूची या वर्ग उदाहरण):

  • उथली प्रतिलिपि एक नई यौगिक वस्तु का निर्माण करती है और फिर (संभव सीमा तक) मूल में पाई जाने वाली वस्तुओं में संदर्भ डालती है।

  • एक गहरी प्रतिलिपि एक नई यौगिक वस्तु का निर्माण करती है और फिर, पुनरावर्ती रूप से, मूल में पाई जाने वाली वस्तुओं में प्रतियां सम्मिलित करती है।

यहाँ थोड़ा प्रदर्शन है:

import copy

a = [1, 2, 3]
b = [4, 5, 6]
c = [a, b]

कॉपी करने के लिए सामान्य असाइनमेंट ऑपरेटिंग का उपयोग करना:

d = c

print id(c) == id(d)          # True - d is the same object as c
print id(c[0]) == id(d[0])    # True - d[0] is the same object as c[0]

उथली प्रति का उपयोग करना:

d = copy.copy(c)

print id(c) == id(d)          # False - d is now a new object
print id(c[0]) == id(d[0])    # True - d[0] is the same object as c[0]

एक गहरी प्रति का उपयोग करना:

d = copy.deepcopy(c)

print id(c) == id(d)          # False - d is now a new object
print id(c[0]) == id(d[0])    # False - d[0] is now a new object

5
क्या उथले प्रति के रूप में समान है?
देषांक

35
@ डॉक नं। उथली प्रतिलिपि एक नई वस्तु का निर्माण करती है, जबकि एक असाइनमेंट मौजूदा ऑब्जेक्ट में नए चर को इंगित करेगा। मौजूदा ऑब्जेक्ट में कोई भी परिवर्तन दोनों चर (असाइनमेंट के साथ) को प्रभावित करेगा।
grc

13
@grc "मौजूदा ऑब्जेक्ट में कोई भी परिवर्तन दोनों चर (असाइनमेंट के साथ) को प्रभावित करेगा" - यह कथन केवल उत्परिवर्तनीय वस्तुओं के लिए सत्य है और स्ट्रिंग, फ्लोट, ट्यूपल्स जैसे अपरिवर्तनीय प्रकारों के लिए नहीं है।
नीरव

1
@grc लेकिन मैं एक उदाहरण की कोशिश की है (मैं यहाँ नया पंक्ति निकाल दें।) अभी भी प्रदर्शन । लेकिन एक सूची है जो पारस्परिक है। list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8] print(list_) print(newlist)newlist[[1, 2], [3, 4]]list_[0]
अल्स्टन

1
@ स्टॉलमैन म्यूट list_[0]है, लेकिन आप इसे म्यूट / संशोधित नहीं कर रहे हैं। कोशिश करो list_[0].append(9)या list_[0][0] = 7इसके बजाय।
grc

46

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

डीप कॉपी नेस्टेड संरचनाओं से संबंधित है। यदि आपके पास सूचियों की सूची है, तो copiesनेस्टेड सूचियों को भी गहरा करें, इसलिए यह पुनरावर्ती प्रतिलिपि है। सिर्फ कॉपी के साथ, आपके पास एक नई बाहरी सूची है, लेकिन आंतरिक सूची संदर्भ हैं।

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


With just copy, you have a new outer list but inner lists are references.आंतरिक सूचियों के लिए, प्रतिलिपि बनाई गई मूल एक से प्रभावित होगी? मैं जैसी सूची list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8]और newlistअवशेषों की सूची बनाता हूं , वैसे ही आंतरिक सूची संदर्भ हैं?
एल्स्टन

1
@Stallman आप यहाँ संदर्भित सूची को नहीं बदल रहे हैं, बस एक नई सूची बना रहे हैं और इसे एक प्रतियों के पहले आइटम के रूप में निर्दिष्ट कर रहे हैं। करने की कोशिशlist_[0][0] = 7
17

20

अपरिवर्तनीय वस्तुओं के लिए, एक प्रति बनाने से बहुत समझ में नहीं आता क्योंकि वे बदलने नहीं जा रहे हैं। परिवर्तनशील वस्तुओं के लिए assignment, copyऔर deepcopyअलग तरह से व्यवहार करता है। उदाहरण के साथ उनमें से प्रत्येक के बारे में बात करते हैं।

एक असाइनमेंट ऑपरेशन, गंतव्य के स्रोत के संदर्भ को बताता है जैसे:

>>> i = [1,2,3]
>>> j=i
>>> hex(id(i)), hex(id(j))
>>> ('0x10296f908', '0x10296f908') #Both addresses are identical

अब iऔर jतकनीकी रूप से एक ही सूची को संदर्भित करता है। दोनों iऔर jएक ही स्मृति पता है। दोनों में से किसी भी अपडेशन को दूसरे को प्रतिबिंबित किया जाएगा। उदाहरण के लिए:

>>> i.append(4)
>>> j
>>> [1,2,3,4] #Destination is updated

>>> j.append(5)
>>> i
>>> [1,2,3,4,5] #Source is updated

दूसरी ओर copyऔर deepcopyचर की एक नई प्रति बनाता है। इसलिए अब मूल चर में परिवर्तन कॉपी चर और इसके विपरीत परिलक्षित नहीं होगा। हालाँकि copy(shallow copy), नेस्टेड ऑब्जेक्ट्स की प्रतिलिपि नहीं बनाता है, इसके बजाय यह नेस्टेड ऑब्जेक्ट्स के संदर्भ की प्रतिलिपि बनाता है। Deepcopy सभी नेस्टेड ऑब्जेक्ट को पुनरावर्ती रूप से कॉपी करता है।

के व्यवहार को प्रदर्शित करने के लिए कुछ उदाहरण copyऔर deepcopy:

उपयोग करके फ्लैट सूची उदाहरण copy:

>>> import copy
>>> i = [1,2,3]
>>> j = copy.copy(i)
>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are different

>>> i.append(4)
>>> j
>>> [1,2,3] #Updation of original list didn't affected copied variable

नेस्टेड सूची उदाहरण का उपयोग कर copy:

>>> import copy
>>> i = [1,2,3,[4,5]]
>>> j = copy.copy(i)

>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are still different

>>> hex(id(i[3])), hex(id(j[3]))
>>> ('0x10296f908', '0x10296f908') #Nested lists have same address

>>> i[3].append(6)
>>> j
>>> [1,2,3,[4,5,6]] #Updation of original nested list updated the copy as well

उपयोग करके फ्लैट सूची उदाहरण deepcopy:

>>> import copy
>>> i = [1,2,3]
>>> j = copy.deepcopy(i)
>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are different

>>> i.append(4)
>>> j
>>> [1,2,3] #Updation of original list didn't affected copied variable

नेस्टेड सूची उदाहरण का उपयोग कर deepcopy:

>>> import copy
>>> i = [1,2,3,[4,5]]
>>> j = copy.deepcopy(i)

>>> hex(id(i)), hex(id(j))
>>> ('0x102b9b7c8', '0x102971cc8') #Both addresses are still different

>>> hex(id(i[3])), hex(id(j[3]))
>>> ('0x10296f908', '0x102b9b7c8') #Nested lists have different addresses

>>> i[3].append(6)
>>> j
>>> [1,2,3,[4,5]] #Updation of original nested list didn't affected the copied variable    

18

आइए एक ग्राफिकल उदाहरण में देखें कि निम्नलिखित कोड कैसे निष्पादित किया जाता है:

import copy

class Foo(object):
    def __init__(self):
        pass


a = [Foo(), Foo()]
shallow = copy.copy(a)
deep = copy.deepcopy(a)

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


5

ए, बी, सी, डी, ए, बी 1, सी 1 और डी 1 स्मृति में वस्तुओं के संदर्भ हैं, जो विशिष्ट रूप से उनकी आईडी द्वारा पहचाने जाते हैं।

एक असाइनमेंट ऑपरेशन मेमोरी में ऑब्जेक्ट के लिए एक संदर्भ लेता है और एक नए नाम के लिए उस संदर्भ को असाइन करता है। c=[1,2,3,4]एक असाइनमेंट है जो उन चार पूर्णांकों से युक्त एक नई सूची ऑब्जेक्ट बनाता है, और उस ऑब्जेक्ट के संदर्भ को असाइन करता है cc1=cएक असाइनमेंट है जो एक ही ऑब्जेक्ट के लिए एक ही संदर्भ लेता है और इसे असाइन करता है c1। चूँकि सूची परिवर्तनशील है, इसलिए उस सूची में जो कुछ भी होता है, वह इस बात पर ध्यान दिए बिना दिखाई देगा कि आप इस तक पहुँचते हैं cया नहीं c1, क्योंकि वे दोनों एक ही वस्तु को संदर्भित करते हैं।

c1=copy.copy(c)एक "उथली प्रति" है जो एक नई सूची बनाती है और नई सूची के संदर्भ को निर्दिष्ट करती है c1cअभी भी मूल सूची की ओर इशारा करता है। इसलिए, यदि आप सूची को संशोधित करते हैं c1, तो सूची जो cसंदर्भित करती है वह नहीं बदलेगी।

नकल की अवधारणा पूर्णांक और तार जैसी अपरिवर्तनीय वस्तुओं के लिए अप्रासंगिक है। चूंकि आप उन वस्तुओं को संशोधित नहीं कर सकते हैं, इसलिए विभिन्न स्थानों पर मेमोरी में एक ही मूल्य की दो प्रतियां रखने की आवश्यकता नहीं है। इसलिए पूर्णांक और तार, और कुछ अन्य वस्तुएं जिनमें कॉपी करने की अवधारणा लागू नहीं होती है, उन्हें बस पुन: असाइन किया जाता है। यही कारण है कि समान आईडी में आपके उदाहरण aऔर bपरिणाम हैं।

c1=copy.deepcopy(c)एक "गहरी प्रति" है, लेकिन यह इस उदाहरण में उथली प्रति के समान है। दीप प्रतियाँ उस उथली प्रतियों से भिन्न होती हैं जो उथली प्रतियों में ही वस्तु की एक नई प्रतिलिपि बनाती हैं, लेकिन उस वस्तु के अंदर कोई भी संदर्भ स्वयं कॉपी नहीं होगा। आपके उदाहरण में, आपकी सूची में इसके अंदर केवल पूर्णांक हैं (जो अपरिवर्तनीय हैं), और जैसा कि पहले चर्चा की गई थी, उन लोगों को कॉपी करने की कोई आवश्यकता नहीं है। तो गहरी प्रतिलिपि का "गहरा" हिस्सा लागू नहीं होता है। हालाँकि, इस अधिक जटिल सूची पर विचार करें:

e = [[1, 2],[4, 5, 6],[7, 8, 9]]

यह एक सूची है जिसमें अन्य सूचियाँ हैं (आप इसे द्वि-आयामी सरणी के रूप में भी वर्णित कर सकते हैं)।

यदि आप एक "उथली प्रतिलिपि" चलाते हैं e, तो इसकी प्रतिलिपि बनाते हुए e1, आप पाएंगे कि सूची की आईडी बदल जाती है, लेकिन सूची की प्रत्येक प्रतिलिपि में एक ही तीन सूचियों के संदर्भ हैं - जो पूर्णांक के अंदर की सूची हैं। इसका मतलब है कि अगर आप करना चाहते थे e[0].append(3), तो eहोगा [[1, 2, 3],[4, 5, 6],[7, 8, 9]]। लेकिन e1होगा भी [[1, 2, 3],[4, 5, 6],[7, 8, 9]]। दूसरी ओर, यदि आप बाद में करते हैं e.append([10, 11, 12]), eतो होगा [[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12]]। लेकिन e1फिर भी होगा [[1, 2, 3],[4, 5, 6],[7, 8, 9]]। ऐसा इसलिए है क्योंकि बाहरी सूचियाँ अलग-अलग ऑब्जेक्ट्स हैं जो शुरू में प्रत्येक में तीन आंतरिक सूचियों के तीन संदर्भ होते हैं। यदि आप आंतरिक सूचियों को संशोधित करते हैं, तो आप उन बदलावों को देख सकते हैं, भले ही आप उन्हें एक प्रति या दूसरे के माध्यम से देख रहे हों। लेकिन यदि आप उपरोक्त में से किसी एक बाहरी सूची को संशोधित करते हैं, तोeमूल तीन सूचियों में तीन संदर्भ शामिल हैं और एक नई सूची के लिए एक और संदर्भ। और e1अभी भी केवल मूल तीन संदर्भ शामिल हैं।

एक 'डीप कॉपी' न केवल बाहरी सूची को डुप्लिकेट करेगा, बल्कि यह सूचियों के अंदर भी जाएगा और आंतरिक सूचियों को डुप्लिकेट करेगा, ताकि दो परिणामी वस्तुओं में कोई समान संदर्भ न हो (जहाँ तक परस्पर वस्तुओं का संबंध है) । अगर आंतरिक सूचियों में उनके अंदर (या अन्य वस्तुएं जैसे शब्दकोशों) की सूची होती, तो वे भी दोहराई जातीं। वह 'डीप कॉपी' का 'गहरा' हिस्सा है।


2

अजगर में, जब हम किसी अन्य वस्तु की सूची, टुपल्स, तानाशाही, आदि जैसी वस्तुओं को आमतौर पर '=' चिन्ह के साथ असाइन करते हैं, तो अजगर संदर्भ द्वारा कॉपी बनाता है । अर्थात्, हम कहते हैं कि हमारे पास इस तरह की सूची है:

list1 = [ [ 'a' , 'b' , 'c' ] , [ 'd' , 'e' , 'f' ]  ]

और हम इस सूची में एक और सूची प्रदान करते हैं:

list2 = list1

तब यदि हम अजगर टर्मिनल में list2 प्रिंट करते हैं तो हमें यह मिलेगा:

list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ']  ]

List1 & list2 दोनों एक ही मेमोरी लोकेशन की ओर इशारा कर रहे हैं, किसी भी एक में किसी भी बदलाव के परिणामस्वरूप दोनों ऑब्जेक्ट्स में दिखाई देने वाले बदलाव होंगे, अर्थात दोनों ऑब्जेक्ट्स एक ही मेमोरी लोकेशन की ओर इशारा करते हैं। अगर हम इस तरह से list1 को बदलते हैं:

list1[0][0] = 'x’
list1.append( [ 'g'] )

तब list1 और list2 दोनों होंगे:

list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g'] ]
list2 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g’ ] ]

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

import copy

list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ']  ]      # assigning a list
list2 = copy.copy(list1)       # shallow copy is done using copy function of copy module

list1.append ( [ 'g', 'h', 'i'] )   # appending another list to list1

print list1
list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ]
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] ]

सूचना, सूची 2 अप्रभावित रहता है, लेकिन यदि हम बाल वस्तुओं में परिवर्तन करते हैं जैसे:

list1[0][0] = 'x’

तब list1 और list2 दोनों को परिवर्तन मिलेगा:

list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ] 
list2 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] ]

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

import copy

list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f ']  ]         # assigning a list
list2 = deepcopy.copy(list1)       # deep copy is done using deepcopy function of copy module

list1.append ( [ 'g', 'h', 'i'] )   # appending another list to list1

print list1
list1 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ]
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f '] ]

सूचना, सूची 2 अप्रभावित रहता है, लेकिन यदि हम बाल वस्तुओं में परिवर्तन करते हैं जैसे:

list1[0][0] = 'x’

तब भी list2 अप्रभावित रहेगा क्योंकि सभी बच्चे ऑब्जेक्ट्स और पैरेंट ऑब्जेक्ट अलग-अलग मेमोरी लोकेशन पर जाते हैं:

list1 = [ [ 'x', 'b', 'c'] , [ 'd', 'e', ' f '] , [ 'g', 'h', 'i'] ] 
list2 = [ [ 'a', 'b', 'c'] , [ 'd', 'e', ' f  ' ] ]

आशा करता हूँ की ये काम करेगा।


0

नीचे कोड असाइनमेंट के बीच के अंतर को दर्शाता है, कॉपी विधि का उपयोग करके उथली प्रतिलिपि, (स्लाइस) का उपयोग करके उथली प्रतिलिपि [:] और डीपकोपी। उदाहरण के नीचे मतभेदों को और अधिक स्पष्ट करके नेस्टेड सूचियों का उपयोग करता है।

from copy import deepcopy

########"List assignment (does not create a copy) ############
l1 = [1,2,3, [4,5,6], [7,8,9]]
l1_assigned = l1

print(l1)
print(l1_assigned)

print(id(l1), id(l1_assigned))
print(id(l1[3]), id(l1_assigned[3]))
print(id(l1[3][0]), id(l1_assigned[3][0]))

l1[3][0] = 100
l1.pop(4)
l1.remove(1)


print(l1)
print(l1_assigned)
print("###################################")

########"List copy using copy method (shallow copy)############

l2 = [1,2,3, [4,5,6], [7,8,9]]
l2_copy = l2.copy()

print(l2)
print(l2_copy)

print(id(l2), id(l2_copy))
print(id(l2[3]), id(l2_copy[3]))
print(id(l2[3][0]), id(l2_copy[3][0]))
l2[3][0] = 100
l2.pop(4)
l2.remove(1)


print(l2)
print(l2_copy)

print("###################################")

########"List copy using slice (shallow copy)############

l3 = [1,2,3, [4,5,6], [7,8,9]]
l3_slice = l3[:]

print(l3)
print(l3_slice)

print(id(l3), id(l3_slice))
print(id(l3[3]), id(l3_slice[3]))
print(id(l3[3][0]), id(l3_slice[3][0]))

l3[3][0] = 100
l3.pop(4)
l3.remove(1)


print(l3)
print(l3_slice)

print("###################################")

########"List copy using deepcopy ############

l4 = [1,2,3, [4,5,6], [7,8,9]]
l4_deep = deepcopy(l4)

print(l4)
print(l4_deep)

print(id(l4), id(l4_deep))
print(id(l4[3]), id(l4_deep[3]))
print(id(l4[3][0]), id(l4_deep[3][0]))

l4[3][0] = 100
l4.pop(4)
l4.remove(1)

print(l4)
print(l4_deep)
print("##########################")
print(l4[2], id(l4[2]))
print(l4_deep[3], id(l4_deep[3]))

print(l4[2][0], id(l4[2][0]))
print(l4_deep[3][0], id(l4_deep[3][0]))

0

लेने के लिए GIST यह है: "सामान्य असाइनमेंट" का उपयोग करके उथली सूचियों (कोई भी उप-कलाकार, सिर्फ एक तत्व) के साथ व्यवहार करना "उथल-पुथल" पैदा करता है जब आप उथली सूची बनाते हैं और तब आप इस सामान्य असाइनमेंट का उपयोग करके इस सूची की एक प्रति बनाते हैं। । यह "दुष्प्रभाव" तब होता है जब आप बनाई गई प्रतिलिपि सूची के किसी भी तत्व को बदलते हैं, क्योंकि यह स्वचालित रूप से मूल सूची के समान तत्वों को बदल देगा। जब copyयह काम आता है, क्योंकि यह कॉपी तत्वों को बदलते समय मूल सूची तत्वों को नहीं बदलेगा।

दूसरी ओर, copyएक "साइड इफेक्ट" भी होता है, जब आपके पास एक सूची होती है, जिसमें सूची (उप_सूची) होती है, और deepcopyइसे हल करती है। उदाहरण के लिए यदि आप एक बड़ी सूची बनाते हैं, जिसमें नेस्टेड सूची (सब_लिस्ट) होती है, और आप इस बड़ी सूची (मूल सूची) की एक प्रति बनाते हैं। "साइड इफेक्ट" तब उत्पन्न होगा जब आप कॉपी सूची के उप_वादियों को संशोधित करेंगे जो स्वचालित रूप से बड़ी सूची के उप_वादियों को संशोधित करेगा। कभी-कभी (कुछ परियोजनाओं में) आप बड़ी सूची (आपकी मूल सूची) रखना चाहते हैं, क्योंकि यह संशोधन के बिना है, और आप सभी चाहते हैं कि इसके तत्वों (सब_लिस्ट्स) की एक प्रतिलिपि बनाई जाए। उसके लिए, आपके समाधान का उपयोग करना है deepcopyजो इस "साइड इफेक्ट" का ध्यान रखेगा और मूल सामग्री को संशोधित किए बिना एक प्रतिलिपि बनाता है।

के विभिन्न व्यवहार copyऔर deep copyसंचालन केवल यौगिक वस्तुओं की चिंता करते हैं (यानी: ऐसी वस्तुएं जिनमें सूची जैसी अन्य वस्तुएं होती हैं)।

इस सरल कोड उदाहरण में सचित्र अंतर हैं:

प्रथम

आइए देखें कि copyमूल सूची और इस सूची की प्रतिलिपि बनाकर (उथला) कैसे व्यवहार करता है:

import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.copy(original_list)

अब, कुछ printपरीक्षण चलाते हैं और देखते हैं कि इसकी प्रतिलिपि सूची की तुलना में मूल सूची कैसे व्यवहार करती है:

original_list और copy_list के अलग-अलग पते हैं

print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328

मूल_सूची और कॉपी_लिस्ट के तत्वों के पते समान हैं

print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440

मूल_सूची और कॉपी_सूची के उप-पते एक ही पते के होते हैं

print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x1faef08 0x1faef08

मूल_सूची तत्वों को संशोधित करना copy_list तत्वों को संशोधित नहीं करता है

original_list.append(6)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]

copy_list तत्वों को संशोधित करना original_list तत्वों को संशोधित नहीं करता है

copy_list.append(7)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]

मूल_सूची उप_सूची को संशोधित करके स्वचालित रूप से प्रतिलिपि_सूची उप_सूची को संशोधित करता है

original_list[5].append('c')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 7]

copy_list sub_elements को स्वचालित रूप से मूल_लिस्ट sub_elements संशोधित करता है

copy_list[5].append('d')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 7]

दूसरा

आइए देखें कि हम कैसे deepcopyव्यवहार करते हैं, जैसा कि हमने किया था copy(एक मूल सूची और इस सूची की एक प्रति बनाकर):

import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.copy(original_list)

अब, कुछ printपरीक्षण चलाते हैं और देखते हैं कि इसकी प्रतिलिपि सूची की तुलना में मूल सूची कैसे व्यवहार करती है:

import copy
original_list = [1, 2, 3, 4, 5, ['a', 'b']]
copy_list = copy.deepcopy(original_list)

original_list और copy_list के अलग-अलग पते हैं

print(hex(id(original_list)), hex(id(copy_list))) # 0x1fb3030 0x1fb3328

मूल_सूची और कॉपी_लिस्ट के तत्वों के पते समान हैं

print(hex(id(original_list[1])), hex(id(copy_list[1]))) # 0x537ed440 0x537ed440

मूल_सूची और प्रतिलिपि_सूची के उप_ अलग-अलग पते हैं

print(hex(id(original_list[5])), hex(id(copy_list[5]))) # 0x24eef08 0x24f3300

मूल_सूची तत्वों को संशोधित करना copy_list तत्वों को संशोधित नहीं करता है

original_list.append(6)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b']]

copy_list तत्वों को संशोधित करना original_list तत्वों को संशोधित नहीं करता है

copy_list.append(7)
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]

मूल_सूची उप_ संशोधनों को संशोधित करना प्रतिलिपि_सूची उप_सूची को संशोधित नहीं करता है

original_list[5].append('c')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b'], 7]

copy_list sub_elements को संशोधित करने से original_list उप_सूची को संशोधित नहीं किया जाता है

copy_list[5].append('d')
print("original_list is:", original_list) # original_list is: [1, 2, 3, 4, 5, ['a', 'b', 'c', 'd'], 6]
print("copy_list is:", copy_list) # copy_list is: [1, 2, 3, 4, 5, ['a', 'b', 'd'], 7]

0

यह सुनिश्चित नहीं है कि यह ऊपर उल्लेख किया गया है या नहीं, लेकिन यह बहुत महत्वपूर्ण है कि मूल वस्तु के संदर्भ में .copy () बनाएं। यदि आप कॉपी किए गए ऑब्जेक्ट को बदलते हैं - तो आप मूल ऑब्जेक्ट को बदलते हैं। .deepcopy () नई ऑब्जेक्ट बनाता है और नए को ओरिजिनल ऑब्जेक्ट की असली कॉपी करता है। नए डीपकोपिड ऑब्जेक्ट को बदलने से मूल ऑब्जेक्ट प्रभावित नहीं होता है।

और हाँ, .deepcopy () मूल ऑब्जेक्ट को पुनरावर्ती रूप से कॉपी करता है, जबकि .copy () मूल ऑब्जेक्ट के प्रथम-स्तरीय डेटा के लिए एक संदर्भ ऑब्जेक्ट बनाता है।

तो कॉपी / / .copy और (.deepcopy) के बीच अंतर को संदर्भित करना महत्वपूर्ण है।


0

डीप कॉपी नेस्टेड संरचनाओं से संबंधित है। यदि आपके पास सूचियों की सूची है, तो deepcopy नेस्टेड सूचियों को भी कॉपी करता है, इसलिए यह पुनरावर्ती प्रतिलिपि है। सिर्फ कॉपी के साथ, आपके पास एक नई बाहरी सूची है, लेकिन आंतरिक सूची संदर्भ हैं। असाइनमेंट की नकल नहीं होती है। एक्स के लिए

import copy
spam = [[0, 1, 2, 3], 4, 5]
cheese = copy.copy(spam)
cheese.append(3)
cheese[0].append(3)
print(spam)
print(cheese)

उत्पादन

[[०, १, २, ३, ३], ४, ५] [[०, १, २, ३, ३], ४, ५, ३] बाहरी सूची की कॉपी विधि कॉपी सूची नई सूची में लेकिन आंतरिक सूची है दोनों सूची के लिए अभी भी समान है इसलिए यदि आप किसी सूची की आंतरिक सूची में परिवर्तन करते हैं तो यह दोनों सूची को प्रभावित करेगा।

लेकिन अगर आप डीप कॉपी का उपयोग करते हैं तो यह आंतरिक सूची के लिए भी नया उदाहरण बनाएगा।

import copy
spam = [[0, 1, 2, 3], 4, 5]
cheese = copy.deepcopy(spam)
cheese.append(3)
cheese[0].append(3)
print(spam)
print(cheese)

उत्पादन

[०, १, २, ३] [[०, १, २, ३, ३], ४, ५, ३]


-1
>>lst=[1,2,3,4,5]

>>a=lst

>>b=lst[:]

>>> b
[1, 2, 3, 4, 5]

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

>>> lst is b
False

>>> lst is a
True

>>> id(lst)
46263192

>>> id(a)
46263192 ------>  See here id of a and id of lst is same so its called deep copy and even boolean answer is true

>>> id(b)
46263512 ------>  See here id of b and id of lst is not same so its called shallow copy and even boolean answer is false although output looks same.

aकी एक गहरी प्रतिलिपि नहीं है lst!
जॉर्जी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.