Apa perbedaan antara operasi penyalinan dangkal, deepcopy, dan operasi normal?

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))

Saya mendapatkan hasil sebagai berikut:

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

Jika saya melakukan deepcopy:

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

hasilnya sama:

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

Jika saya mengerjakan operasi penugasan:

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

maka hasilnya adalah:

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

Adakah yang bisa menjelaskan apa yang sebenarnya membuat perbedaan di antara salinan? Apakah itu terkait dengan objek yang bisa berubah & tidak berubah? Jika demikian, dapatkah Anda menjelaskannya kepada saya?

Deeshank
sumber

Jawaban:

364

Operasi penugasan normal hanya akan mengarahkan variabel baru ke objek yang ada. The docs menjelaskan perbedaan antara dangkal dan salinan yang mendalam:

Perbedaan antara penyalinan dangkal dan dalam hanya relevan untuk objek majemuk (objek yang berisi objek lain, seperti daftar atau instance kelas):

  • Salinan dangkal membangun objek majemuk baru dan kemudian (sejauh mungkin) menyisipkan referensi ke dalamnya ke objek yang ditemukan dalam aslinya.

  • Salinan dalam membangun objek majemuk baru dan kemudian, secara rekursif, memasukkan salinan ke dalamnya objek yang ditemukan dalam aslinya.

Ini sedikit demonstrasi:

import copy

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

Menggunakan operasi penugasan normal untuk menyalin:

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]

Menggunakan salinan dangkal:

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]

Menggunakan salinan dalam:

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
grc
sumber
5
apakah assginment sama dengan copy dangkal?
deeshank
35
@Shank No. Salinan dangkal membangun objek baru, sementara tugas hanya akan mengarahkan variabel baru pada objek yang ada. Setiap perubahan pada objek yang ada akan mempengaruhi kedua variabel (dengan penugasan).
grc
13
@ grc "Setiap perubahan pada objek yang ada akan memengaruhi kedua variabel (dengan penugasan)" - pernyataan ini hanya berlaku untuk objek yang dapat diubah dan bukan tipe yang tidak dapat diubah seperti string, float, tuple.
Neerav
1
@grc Tapi aku telah mencoba contoh (saya menghapus baris baru di sini.) list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8] print(list_) print(newlist)The newlistdisplay masih [[1, 2], [3, 4]]. Tetapi list_[0]adalah daftar yang bisa berubah.
Alston
1
@Stallman list_[0]bisa berubah, tetapi Anda tidak bermutasi / memodifikasinya. Coba list_[0].append(9)atau list_[0][0] = 7sebaliknya.
grc
46

Untuk objek yang tidak dapat diubah, tidak perlu menyalin karena data tidak akan pernah berubah, jadi Python menggunakan data yang sama; id selalu sama. Untuk objek yang bisa berubah, karena mereka berpotensi berubah, salinan [dangkal] akan membuat objek baru.

Salinan mendalam terkait dengan struktur bersarang. Jika Anda memiliki daftar daftar, maka deepcopy copiesdaftar yang bersarang juga, jadi itu adalah salinan rekursif. Dengan hanya menyalin, Anda memiliki daftar luar baru, tetapi daftar dalam adalah referensi.

Tugas tidak menyalin. Itu hanya mengatur referensi ke data lama. Jadi, Anda perlu menyalin untuk membuat daftar baru dengan konten yang sama.

perreal
sumber
With just copy, you have a new outer list but inner lists are references.Untuk daftar dalam, apakah yang disalin dipengaruhi oleh yang asli? Saya membuat daftar daftar suka list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8]dan newlisttetap sama, jadi apakah daftar dalam adalah referensi?
Alston
1
@Stallman Anda tidak mengubah daftar referensi di sini, cukup membuat daftar baru dan menetapkannya sebagai item pertama dari salah satu salinan. coba lakukanlist_[0][0] = 7
perreal
20

Untuk objek yang tidak dapat diubah, membuat salinan tidak masuk akal karena tidak akan berubah. Untuk objek yang bisa berubah assignment, copydan deepcopyberperilaku berbeda. Mari kita bicarakan masing-masing dengan contoh.

Operasi penugasan hanya memberikan referensi sumber ke tujuan misalnya:

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

Sekarang idan secara jteknis mengacu pada daftar yang sama. Keduanya idan jmemiliki alamat memori yang sama. Setiap pembaruan ke salah satu dari mereka akan tercermin ke yang lain. misalnya:

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

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

Di sisi lain copydan deepcopymembuat salinan variabel baru. Jadi sekarang perubahan ke variabel asli tidak akan tercermin ke variabel salin dan sebaliknya. Namun copy(shallow copy), jangan membuat salinan objek bersarang, melainkan hanya menyalin referensi objek bersarang. Deepcopy menyalin semua objek yang bersarang secara rekursif.

Beberapa contoh untuk menunjukkan perilaku copydan deepcopy:

Contoh daftar datar menggunakan 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

Contoh daftar bersarang menggunakan 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

Contoh daftar datar menggunakan 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

Contoh daftar bersarang menggunakan 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    
Sohaib Farooqi
sumber
18

Mari kita lihat dalam contoh grafis bagaimana kode berikut dijalankan:

import copy

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


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

masukkan deskripsi gambar di sini

pengguna1767754
sumber
5

a, b, c, d, a1, b1, c1 dan d1 adalah referensi ke objek dalam memori, yang secara unik diidentifikasi oleh id mereka.

Operasi penugasan mengambil referensi ke objek di memori dan menetapkan referensi itu ke nama baru. c=[1,2,3,4]adalah tugas yang membuat objek daftar baru yang berisi keempat bilangan bulat, dan memberikan referensi ke objek tersebut c. c1=cadalah penugasan yang mengambil referensi yang sama ke objek yang sama dan menugaskannya untuk c1. Karena daftar dapat diubah, apa pun yang terjadi pada daftar itu akan terlihat terlepas dari apakah Anda mengaksesnya catauc1 , karena keduanya merujuk objek yang sama.

c1=copy.copy(c)adalah "salinan dangkal" yang membuat daftar baru dan memberikan referensi ke daftar baru tersebut c1. cmasih menunjuk ke daftar asli. Jadi, jika Anda mengubah daftar di c1, daftar yang cmerujuk tidak akan berubah.

Konsep penyalinan tidak relevan dengan objek yang tidak dapat diubah seperti bilangan bulat dan string. Karena Anda tidak dapat memodifikasi objek-objek itu, tidak perlu memiliki dua salinan dengan nilai yang sama di memori di lokasi yang berbeda. Jadi bilangan bulat dan string, dan beberapa objek lain dimana konsep penyalinan tidak berlaku, hanya dipindahkan. Inilah sebabnya contoh Anda dengan adan bmenghasilkan id yang identik.

c1=copy.deepcopy(c)adalah "salinan dalam", tetapi fungsinya sama dengan salinan dangkal dalam contoh ini. Salinan dalam berbeda dari salinan dangkal dalam salinan yang dangkal akan membuat salinan baru dari objek itu sendiri, tetapi setiap referensi di dalam objek itu sendiri tidak akan disalin. Dalam contoh Anda, daftar Anda hanya memiliki bilangan bulat di dalamnya (yang tidak dapat diubah), dan seperti yang dibahas sebelumnya tidak perlu menyalinnya. Jadi bagian "dalam" dari salinan dalam tidak berlaku. Namun, pertimbangkan daftar yang lebih kompleks ini:

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

Ini adalah daftar yang berisi daftar lain (Anda juga bisa menggambarkannya sebagai array dua dimensi).

Jika Anda menjalankan "salinan dangkal" e, menyalinnya e1, Anda akan menemukan bahwa id daftar berubah, tetapi setiap salinan daftar berisi referensi ke tiga daftar yang sama - daftar dengan bilangan bulat di dalamnya. Itu berarti bahwa jika Anda melakukannya e[0].append(3), maka itu eakan terjadi [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. Tetapi e1juga akan [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. Di sisi lain, jika Anda kemudian melakukannya e.append([10, 11, 12]), eakan menjadi [[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12]]. Tetapie1 masih akan[[1, 2, 3],[4, 5, 6],[7, 8, 9]] . Itu karena daftar luar adalah objek terpisah yang awalnya masing-masing berisi tiga referensi ke tiga daftar dalam. Jika Anda memodifikasi daftar dalam, Anda dapat melihat perubahan itu tidak masalah jika Anda melihatnya melalui satu salinan atau yang lain. Tetapi jika Anda memodifikasi salah satu daftar terluar seperti di atas, makaeberisi tiga referensi ke tiga daftar asli ditambah satu lagi referensi ke daftar baru. Dan e1masih hanya berisi tiga referensi asli.

'Salinan dalam' tidak hanya akan menduplikasi daftar luar, tetapi juga akan masuk ke dalam daftar dan menduplikasi daftar dalam, sehingga dua objek yang dihasilkan tidak mengandung referensi yang sama (sejauh menyangkut objek yang dapat diubah) . Jika daftar dalam memiliki daftar lebih lanjut (atau objek lain seperti kamus) di dalamnya, mereka juga akan digandakan. Itulah bagian 'dalam' dari 'salinan dalam'.

Andrew Gorcester
sumber
2

Dalam python, ketika kita menetapkan objek seperti daftar, tupel, dict, dll ke objek lain biasanya dengan tanda '=', python membuat salinan dengan referensi . Artinya, katakanlah kita memiliki daftar daftar seperti ini:

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

dan kami menetapkan daftar lain untuk daftar ini seperti:

list2 = list1

maka jika kita mencetak list2 di terminal python kita akan mendapatkan ini:

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

Baik list1 & list2 menunjuk ke lokasi memori yang sama, setiap perubahan pada salah satu dari mereka akan menghasilkan perubahan yang terlihat di kedua objek, yaitu kedua objek menunjuk ke lokasi memori yang sama. Jika kita mengubah list1 seperti ini:

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

maka list1 dan list2 akan menjadi:

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

Sekarang datang ke salinan Dangkal , ketika dua objek disalin melalui salinan dangkal, objek anak dari kedua objek induk merujuk ke lokasi memori yang sama tetapi setiap perubahan baru lebih lanjut di salah satu objek yang disalin akan independen satu sama lain. Mari kita pahami ini dengan contoh kecil. Misalkan kita memiliki cuplikan kode kecil ini:

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

perhatikan, list2 tetap tidak terpengaruh, tetapi jika kita membuat perubahan pada objek anak seperti:

list1[0][0] = 'x’

maka list1 dan list2 akan mendapatkan perubahan:

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

Sekarang, Deep copy membantu dalam menciptakan objek yang benar-benar terisolasi satu sama lain. Jika dua objek disalin melalui Salin Jauh maka kedua orang tua & anaknya akan menunjuk ke lokasi memori yang berbeda. Contoh:

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

perhatikan, list2 tetap tidak terpengaruh, tetapi jika kita membuat perubahan pada objek anak seperti:

list1[0][0] = 'x’

kemudian list2 tidak akan terpengaruh karena semua objek anak dan objek induk menunjuk ke lokasi memori yang berbeda:

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

Semoga ini bisa membantu.

Nitish Chauhan
sumber
0

Kode di bawah ini menunjukkan perbedaan antara penugasan, salinan dangkal menggunakan metode salin, salinan dangkal menggunakan (slice) [:] dan deepcopy. Contoh di bawah ini menggunakan daftar bersarang di sana dengan membuat perbedaan lebih jelas.

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]))
Sandeep
sumber
0

GIST yang harus diambil adalah ini: Berurusan dengan daftar yang dangkal (tidak ada sub_lists, hanya satu elemen) menggunakan "penugasan normal" menimbulkan "efek samping" ketika Anda membuat daftar dangkal dan kemudian Anda membuat salinan daftar ini menggunakan "penugasan normal" . "Efek samping" ini adalah ketika Anda mengubah elemen apa pun dari daftar salinan yang dibuat, karena itu akan secara otomatis mengubah elemen yang sama dari daftar asli. Itu ketika copyberguna, karena itu tidak akan mengubah elemen daftar asli ketika mengubah elemen salin.

Di sisi lain, copymemang memiliki "efek samping" juga, ketika Anda memiliki daftar yang memiliki daftar di dalamnya (sub_lists), dan deepcopymenyelesaikannya. Misalnya jika Anda membuat daftar besar yang memiliki daftar bersarang di dalamnya (sub_lists), dan Anda membuat salinan daftar besar ini (daftar asli). "Efek samping" akan muncul ketika Anda memodifikasi sub_lists dari daftar salinan yang secara otomatis akan mengubah sub_lists dari daftar besar. Terkadang (dalam beberapa proyek) Anda ingin menyimpan daftar besar (daftar asli Anda) karena tanpa modifikasi, dan semua yang Anda inginkan adalah membuat salinan elemen-elemennya (sub_lists). Untuk itu, solusi Anda adalah menggunakan deepcopyyang akan menangani "efek samping" ini dan membuat salinan tanpa mengubah konten asli.

Perilaku copydan deep copyoperasi yang berbeda hanya menyangkut objek majemuk (yaitu: objek yang berisi objek lain seperti daftar).

Berikut adalah perbedaan yang diilustrasikan dalam contoh kode sederhana ini:

Pertama

mari kita periksa bagaimana copy(dangkal) berperilaku, dengan membuat daftar asli dan salinan daftar ini:

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

Sekarang, mari kita jalankan beberapa printtes dan lihat bagaimana perilaku daftar asli dibandingkan dengan daftar salinannya:

original_list dan copy_list memiliki alamat berbeda

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

elemen original_list dan copy_list memiliki alamat yang sama

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

sub_elements dari original_list dan copy_list memiliki alamat yang sama

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

memodifikasi elemen original_list TIDAK mengubah elemen 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']]

memodifikasi elemen copy_list TIDAK mengubah elemen 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]

memodifikasi sub_elemen original_list secara otomatis memodifikasi sub_elemen copy_list

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]

memodifikasi sub_elemen copy_list secara otomatis memodifikasi sub_elemen 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', 'c', 'd'], 7]

Kedua

mari kita periksa bagaimana deepcopyberperilaku, dengan melakukan hal yang sama seperti yang kita lakukan dengan copy(membuat daftar asli dan salinan daftar ini):

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

Sekarang, mari kita jalankan beberapa printtes dan lihat bagaimana perilaku daftar asli dibandingkan dengan daftar salinannya:

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

original_list dan copy_list memiliki alamat berbeda

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

elemen original_list dan copy_list memiliki alamat yang sama

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

sub_elements dari original_list dan copy_list memiliki alamat yang berbeda

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

memodifikasi elemen original_list TIDAK mengubah elemen 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']]

memodifikasi elemen copy_list TIDAK mengubah elemen 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]

memodifikasi sub_elemen original_list TIDAK mengubah sub_elemen copy_list

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]

memodifikasi sub_elemen copy_list TIDAK mengubah sub_elemen 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]
Fouad Boukredine
sumber
0

Tidak yakin apakah itu disebutkan di atas atau tidak, tetapi sangat penting untuk membuktikan bahwa .copy () membuat referensi ke objek asli. Jika Anda mengubah objek yang disalin - Anda mengubah objek aslinya. .deepcopy () membuat objek baru dan melakukan penyalinan nyata dari objek asli ke yang baru. Mengubah objek deepcopied baru tidak mempengaruhi objek asli.

Dan ya, .deepcopy () menyalin objek asli secara rekursif, sementara .copy () membuat objek referensi ke data level pertama dari objek asli.

Jadi perbedaan penyalinan / referensi antara .copy () dan .deepcopy () adalah signifikan.

remort
sumber
0

Salinan mendalam terkait dengan struktur bersarang. Jika Anda memiliki daftar daftar, kemudian menyalin salinan daftar bersarang juga, jadi itu adalah salinan rekursif. Dengan hanya menyalin, Anda memiliki daftar luar baru, tetapi daftar dalam adalah referensi. Tugas tidak menyalin. Untuk Kel

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

Keluaran

[[0, 1, 2, 3, 3], 4, 5] [[0, 1, 2, 3, 3], 4, 5, 3] Menyalin metode menyalin konten daftar luar ke daftar baru tetapi daftar dalam adalah masih sama untuk kedua daftar jadi jika Anda membuat perubahan dalam daftar dalam dari daftar apa pun itu akan mempengaruhi kedua daftar.

Tetapi jika Anda menggunakan Deep copy maka itu akan membuat contoh baru untuk daftar dalam juga.

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

Keluaran

[0, 1, 2, 3] [[0, 1, 2, 3, 3], 4, 5, 3]

Shubham Agarwal
sumber
-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.
sudhir tataraju
sumber
abukan deepcopy lst!
Georgy