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?
sumber
list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8] print(list_) print(newlist)
Thenewlist
display masih[[1, 2], [3, 4]]
. Tetapilist_[0]
adalah daftar yang bisa berubah.list_[0]
bisa berubah, tetapi Anda tidak bermutasi / memodifikasinya. Cobalist_[0].append(9)
ataulist_[0][0] = 7
sebaliknya.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
copies
daftar 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.
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 sukalist_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8]
dannewlist
tetap sama, jadi apakah daftar dalam adalah referensi?list_[0][0] = 7
Untuk objek yang tidak dapat diubah, membuat salinan tidak masuk akal karena tidak akan berubah. Untuk objek yang bisa berubah
assignment
,copy
dandeepcopy
berperilaku berbeda. Mari kita bicarakan masing-masing dengan contoh.Operasi penugasan hanya memberikan referensi sumber ke tujuan misalnya:
Sekarang
i
dan secaraj
teknis mengacu pada daftar yang sama. Keduanyai
danj
memiliki alamat memori yang sama. Setiap pembaruan ke salah satu dari mereka akan tercermin ke yang lain. misalnya:Di sisi lain
copy
dandeepcopy
membuat salinan variabel baru. Jadi sekarang perubahan ke variabel asli tidak akan tercermin ke variabel salin dan sebaliknya. Namuncopy(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
copy
dandeepcopy
:Contoh daftar datar menggunakan
copy
:Contoh daftar bersarang menggunakan
copy
:Contoh daftar datar menggunakan
deepcopy
:Contoh daftar bersarang menggunakan
deepcopy
:sumber
Mari kita lihat dalam contoh grafis bagaimana kode berikut dijalankan:
sumber
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 tersebutc
.c1=c
adalah penugasan yang mengambil referensi yang sama ke objek yang sama dan menugaskannya untukc1
. Karena daftar dapat diubah, apa pun yang terjadi pada daftar itu akan terlihat terlepas dari apakah Anda mengaksesnyac
atauc1
, karena keduanya merujuk objek yang sama.c1=copy.copy(c)
adalah "salinan dangkal" yang membuat daftar baru dan memberikan referensi ke daftar baru tersebutc1
.c
masih menunjuk ke daftar asli. Jadi, jika Anda mengubah daftar dic1
, daftar yangc
merujuk 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
a
danb
menghasilkan 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
, menyalinnyae1
, 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 melakukannyae[0].append(3)
, maka itue
akan terjadi[[1, 2, 3],[4, 5, 6],[7, 8, 9]]
. Tetapie1
juga akan[[1, 2, 3],[4, 5, 6],[7, 8, 9]]
. Di sisi lain, jika Anda kemudian melakukannyae.append([10, 11, 12])
,e
akan 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, makae
berisi tiga referensi ke tiga daftar asli ditambah satu lagi referensi ke daftar baru. Dane1
masih 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'.
sumber
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:
dan kami menetapkan daftar lain untuk daftar ini seperti:
maka jika kita mencetak list2 di terminal python kita akan mendapatkan ini:
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:
maka list1 dan list2 akan menjadi:
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:
perhatikan, list2 tetap tidak terpengaruh, tetapi jika kita membuat perubahan pada objek anak seperti:
maka list1 dan list2 akan mendapatkan perubahan:
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:
perhatikan, list2 tetap tidak terpengaruh, tetapi jika kita membuat perubahan pada objek anak seperti:
kemudian list2 tidak akan terpengaruh karena semua objek anak dan objek induk menunjuk ke lokasi memori yang berbeda:
Semoga ini bisa membantu.
sumber
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.
sumber
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
copy
berguna, karena itu tidak akan mengubah elemen daftar asli ketika mengubah elemen salin.Di sisi lain,
copy
memang memiliki "efek samping" juga, ketika Anda memiliki daftar yang memiliki daftar di dalamnya (sub_lists), dandeepcopy
menyelesaikannya. 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 menggunakandeepcopy
yang akan menangani "efek samping" ini dan membuat salinan tanpa mengubah konten asli.Perilaku
copy
dandeep copy
operasi 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:Sekarang, mari kita jalankan beberapa
print
tes dan lihat bagaimana perilaku daftar asli dibandingkan dengan daftar salinannya:original_list dan copy_list memiliki alamat berbeda
elemen original_list dan copy_list memiliki alamat yang sama
sub_elements dari original_list dan copy_list memiliki alamat yang sama
memodifikasi elemen original_list TIDAK mengubah elemen copy_list
memodifikasi elemen copy_list TIDAK mengubah elemen original_list
memodifikasi sub_elemen original_list secara otomatis memodifikasi sub_elemen copy_list
memodifikasi sub_elemen copy_list secara otomatis memodifikasi sub_elemen original_list
Kedua
mari kita periksa bagaimana
deepcopy
berperilaku, dengan melakukan hal yang sama seperti yang kita lakukan dengancopy
(membuat daftar asli dan salinan daftar ini):Sekarang, mari kita jalankan beberapa
print
tes dan lihat bagaimana perilaku daftar asli dibandingkan dengan daftar salinannya:original_list dan copy_list memiliki alamat berbeda
elemen original_list dan copy_list memiliki alamat yang sama
sub_elements dari original_list dan copy_list memiliki alamat yang berbeda
memodifikasi elemen original_list TIDAK mengubah elemen copy_list
memodifikasi elemen copy_list TIDAK mengubah elemen original_list
memodifikasi sub_elemen original_list TIDAK mengubah sub_elemen copy_list
memodifikasi sub_elemen copy_list TIDAK mengubah sub_elemen original_list
sumber
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.
sumber
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
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.
Keluaran
[0, 1, 2, 3] [[0, 1, 2, 3, 3], 4, 5, 3]
sumber
sumber
a
bukan deepcopylst
!