Sığ kopya, derin kopya ve normal atama işlemi arasındaki fark nedir?


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

Aşağıdaki sonuçları alıyorum:

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

Derin kopya yaparsam:

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

sonuçlar aynı:

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

Atama işlemleri üzerinde çalışırsam:

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

o zaman sonuçlar:

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

Biri kopyalar arasında tam olarak neyin fark yarattığını açıklayabilir mi? Değişken ve değişmez nesnelerle ilgili bir şey mi? Eğer öyleyse, lütfen bana açıklayabilir misiniz?

Yanıtlar:


364

Normal atama işlemleri yeni değişkeni varolan nesneye doğru yönlendirir. Docs Sığ ve derin kopya arasındaki farkı açıklamak:

Sığ ve derin kopyalama arasındaki fark yalnızca bileşik nesnelerle (listeler veya sınıf örnekleri gibi başka nesneler içeren nesneler) ilgilidir:

  • Sığ bir kopya yeni bir bileşik nesne oluşturur ve daha sonra (mümkün olduğu ölçüde) orijinalinde bulunan nesnelere referanslar ekler.

  • Derin bir kopya yeni bir bileşik nesne oluşturur ve daha sonra özyinelemeli olarak, orijinalde bulunan nesnelerin içine kopyalar ekler.

İşte küçük bir gösteri:

import copy

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

Kopyalamak için normal atama işlemlerini kullanma:

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]

Sığ bir kopya kullanma:

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]

Derin bir kopya kullanma:

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
varsayım sığ kopya ile aynı mıdır?
deeshank

35
Sığ bir kopya yeni bir nesne oluştururken bir atama yeni değişkeni varolan nesneye yönlendirir. Varolan nesnede yapılan değişiklikler her iki değişkeni de (atamayla) etkiler.
grc

13
@grc "Varolan nesnede yapılan her iki değişiklik de (atama ile) her iki değişkeni de etkiler" - bu ifade yalnızca değişken nesneler için geçerlidir ve string, float, tuples gibi değişmez türler için geçerli değildir.
Neerav

1
@grc Ama bir örnek denedim (burada yeni bir satır kaldırın.) yine ekran . Ama değişebilen bir liste. list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8] print(list_) print(newlist)newlist[[1, 2], [3, 4]]list_[0]
Alston

1
@Stallman list_[0]değiştirilebilir, ancak onu değiştirmiyor / değiştirmiyorsunuz. Deneyin list_[0].append(9)veya list_[0][0] = 7onun yerine.
grc

46

Değişmez nesneler için, veri asla değişmeyeceğinden kopyalamaya gerek yoktur, bu nedenle Python aynı verileri kullanır; kimlikleri her zaman aynıdır. Değişken nesneler için, potansiyel olarak değişebildikleri için [sığ] kopya yeni bir nesne oluşturur.

Derin kopya, iç içe geçmiş yapılarla ilgilidir. Listeleriniz varsa copies, iç içe listelerin de kopyasını alın, böylece yinelemeli bir kopyadır. Sadece kopya ile, yeni bir dış listeniz var, ancak iç listeler referanslardır.

Ödev kopyalanmıyor. Eski verilere referansı ayarlar. Aynı içeriğe sahip yeni bir liste oluşturmak için kopyaya ihtiyacınız var.


With just copy, you have a new outer list but inner lists are references.İç listeler için, kopyalanan liste orijinal listeden etkilenir mi? Ben gibi listelerin bir listesini oluşturmak list_=[[1,2],[3,4]] newlist = list_.copy() list_[0]=[7,8]ve newlistböylece başvurulardır iç liste yapar, kalıntıların aynı?
Alston

1
@Stallman burada başvurulan listeyi değiştirmiyorsunuz, sadece yeni bir liste oluşturuyorsunuz ve bu listeyi kopyalardan birinin ilk öğesi olarak ataıyorsunuz. yapmaya çalışınlist_[0][0] = 7
perreal

20

Değişmez nesneler için, bir kopya oluşturmak çok fazla mantıklı değildir çünkü değişmeyeceklerdir. Kesilebilir nesneler için assignment, copyve deepcopyfarklı davranır. Her biri hakkında örneklerle konuşalım.

Bir atama işlemi, kaynağın hedefine referansını atar; örneğin:

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

Şimdi ive jteknik olarak aynı listeye atıfta bulunuyor. Hem ive jaynı bellek adresi vardır. Her ikisinde yapılan herhangi bir güncelleme diğerine yansıtılacaktır. Örneğin:

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

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

Öte yandan copyve deepcopydeğişkenin yeni bir kopyasını oluşturur. Şimdi orijinal değişkendeki değişiklikler kopya değişkenine yansıtılmayacak ve tersi de geçerlidir. Ancak copy(shallow copy), iç içe nesnelerin bir kopyasını oluşturmayın, bunun yerine yalnızca iç içe nesnelerin referanslarını kopyalar. Deepcopy, iç içe geçmiş tüm nesneleri özyinelemeli olarak kopyalar.

Bazı örnekler arasında davranış göstermek için copyve deepcopy:

Düz liste örneği kullanarak 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

İç içe liste örneği 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

Düz liste örneği kullanarak 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

İç içe liste örneği 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

Grafiksel bir örnekte aşağıdaki kodun nasıl yürütüldüğüne bakalım:

import copy

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


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

resim açıklamasını buraya girin


5

a, b, c, d, a1, b1, c1 ve d1, bellekteki kimlikleri tarafından benzersiz şekilde tanımlanan nesnelere yapılan göndermelerdir.

Atama işlemi bellekteki nesneye bir başvuru alır ve bu başvuruyu yeni bir ada atar. c=[1,2,3,4]bu dört tamsayıyı içeren yeni bir liste nesnesi oluşturan ve o nesneye başvuruyu atayan bir atamadır c. c1=c, aynı referansı aynı nesneye götüren ve buna atayan bir ödevdir c1. Liste değiştirilebilir olduğundan, listeye erişip erişmediğinize bakılmaksızın cveya c1her ikisi de aynı nesneye başvurduğundan bağımsız olarak bu listeye gelen her şey görünür .

c1=copy.copy(c)yeni bir liste oluşturan ve yeni listeye başvuruyu atayan bir "sığ kopya" dır c1. chala orijinal listeye işaret ediyor. Bu nedenle, adresindeki listeyi değiştirirseniz, başvurulan c1liste cdeğişmez.

Kopyalama kavramı, tamsayılar ve dizgiler gibi değişmez nesnelerle alakasızdır. Bu nesneleri değiştiremeyeceğiniz için, bellekte farklı konumlarda aynı değere sahip iki kopyaya ihtiyaç duyulmaz. Bu nedenle, tamsayılar ve dizeler ve kopyalama kavramının uygulanmadığı diğer bazı nesneler yeniden atanır. Bu yüzden örnekleriniz aynı kimliğe sahip ave bununla bsonuçlanıyor.

c1=copy.deepcopy(c)"derin kopya" dır, ancak bu örnekte sığ bir kopyayla aynı işlevi görür. Derin kopyalar sığ kopyalardan farklıdır, çünkü sığ kopyalar nesnenin kendisinin yeni bir kopyasını oluşturur, ancak o nesnenin içindeki referansların kendisi kopyalanmaz. Örneğinizde, listenizde yalnızca (değişmez olan) tamsayılar vardır ve daha önce tartışıldığı gibi bunları kopyalamaya gerek yoktur. Yani derin kopyanın "derin" kısmı geçerli değildir. Ancak, bu daha karmaşık listeyi göz önünde bulundurun:

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

Bu, diğer listeleri içeren bir listedir (bunu iki boyutlu bir dizi olarak da tanımlayabilirsiniz).

Üzerinde bir "sığ kopya" çalıştırırsanız e, bunu kopyaladığınızda e1, listenin kimliğinin değiştiğini görürsünüz, ancak listenin her kopyası aynı üç listeye (içinde tamsayı içeren listelere) başvurular içerir. Bu, eğer yaparsanız e[0].append(3), o ezaman olur [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. Ama öyle e1de olur [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. Öte yandan, daha sonra yaparsanız e.append([10, 11, 12]), eolurdu [[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12]]. Ama e1yine de olur [[1, 2, 3],[4, 5, 6],[7, 8, 9]]. Bunun nedeni, dış listelerin başlangıçta her biri üç iç listeye üç referans içeren ayrı nesneler olmasıdır. İç listeleri değiştirirseniz, bir kopyadan ya da diğerinden görüntülüyor olsanız da bu değişiklikleri görebilirsiniz. Ancak dış listelerden birini yukarıdaki gibi değiştirirseniz,eorijinal üç listeye üç referans ve yeni bir listeye bir referans daha içerir. Ve e1yine de sadece orijinal üç referansı içerir.

Bir 'derin kopya' sadece dış listeyi kopyalamakla kalmaz, aynı zamanda listelerin içine girer ve iç listeleri çoğaltır, böylece elde edilen iki nesne aynı referanslardan herhangi birini içermez (değiştirilebilir nesneler söz konusu olduğunda) . İç listelerin içinde başka listeler (veya sözlükler gibi başka nesneler) varsa, bunlar da çoğaltılır. Bu, 'derin kopyanın' derin kısmıdır.


2

Python'da, genellikle '=' işaretli başka bir nesneye list, tuples, dict vb. Nesneleri atadığımızda python referans olarak kopyalar oluşturur . Yani, şöyle bir listemiz olduğunu varsayalım:

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

ve bu listeye şöyle bir liste daha veriyoruz:

list2 = list1

o zaman list2'yi python terminalinde yazdırırsak bunu elde ederiz:

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

Liste1 ve liste2'nin her ikisi de aynı bellek konumunu işaret eder, bunlardan herhangi birinde yapılan bir değişiklik her iki nesnede de görünür değişikliklere neden olur, yani her iki nesne de aynı bellek konumuna işaret eder. List1'i bu şekilde değiştirirsek:

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

hem list1 hem de list2:

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

Şimdi Sığ kopyaya geliyor , iki nesne sığ kopya ile kopyalandığında, her iki ana nesnenin alt nesnesi aynı bellek konumuna başvuruyor, ancak kopyalanan nesnelerin herhangi birindeki yeni değişiklikler birbirinden bağımsız olacak. Bunu küçük bir örnekle anlayalım. Bu küçük kod pasajına sahip olduğumuzu varsayalım:

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

dikkat edin, list2 etkilenmez, ancak aşağıdaki gibi alt nesnelerde değişiklik yaparsak:

list1[0][0] = 'x’

hem list1 hem de list2 değişiklik alacaktır:

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

Şimdi, Derin kopya birbirinden tamamen yalıtılmış nesneler oluşturmaya yardımcı olur. İki nesne Derin Kopyalama ile kopyalanırsa, hem üst öğe hem de alt öğesi farklı bir bellek konumuna işaret eder. Misal :

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

dikkat edin, list2 etkilenmez, ancak aşağıdaki gibi alt nesnelerde değişiklik yaparsak:

list1[0][0] = 'x’

ayrıca tüm alt nesneler ve üst nesne farklı bellek konumuna işaret ettiğinden list2 de etkilenmeyecektir:

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

Umarım yardımcı olur.


0

Aşağıdaki kod, atama, kopyalama yöntemini kullanarak sığ kopya, (dilim) [:] kullanarak sığ kopya ve derin kopya arasındaki farkı gösterir. Aşağıdaki örnekte, farkları daha belirgin hale getirerek iç içe listeler kullanılmıştır.

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

Alınacak GIST şudur: "Normal atama" kullanarak sığ listelerle (alt listeler yok, yalnızca tek öğeler) ilgilenmek, sığ bir liste oluşturduğunuzda ve "normal atama" kullanarak bu listenin bir kopyasını oluşturduğunuzda "yan etki" yi artırır . Bu "yan etki", oluşturulan orijinal listenin aynı öğelerini otomatik olarak değiştireceğinden, oluşturulan kopya listesinin herhangi bir öğesini değiştirdiğiniz zamandır. O zaman olduğu copykopya elemanlarını değiştirirken orijinal liste elemanlarını değişmeyecek gibi kullanışlı oluyor.

Öte yandan, copyiçinde listeler (alt_ listeleri) bulunan bir listeniz olduğunda "yan etki" de olur vedeepcopy çözen olur. Örneğin, içinde iç içe listeler bulunan büyük bir liste oluşturursanız (alt listeler) ve bu büyük listenin (orijinal liste) bir kopyasını oluşturursanız. Büyük listenin alt listelerini otomatik olarak değiştiren kopya listesinin alt listelerini değiştirdiğinizde "yan etki" ortaya çıkar. Bazen (bazı projelerde) büyük listeyi (orijinal listeniz) değiştirmeden olduğu gibi tutmak istersiniz ve tek yapmanız gereken öğelerinin bir kopyasını (alt listeler) yapmaktır. Bunun için çözümünüz, deepcopybu "yan etki" ile ilgilenecek ve orijinal içeriği değiştirmeden bir kopyasını yapacak olan kullanmaktır .

Farklı davranışlar copyvedeep copy işlemleri yalnızca bileşik nesnelerle ilgilidir (yani: listeler gibi başka nesneler içeren nesneler).

Bu basit kod örneğinde gösterilen farklılıklar şunlardır:

İlk

copyorijinal bir liste ve bu listenin bir kopyasını oluşturarak (sığ) davranışlarını kontrol edelim :

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

Şimdi, bazı printtestler yapalım ve orijinal listenin kopya listesine kıyasla nasıl davrandığını görelim:

original_list ve copy_list'in farklı adresleri var

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

original_list ve copy_list öğelerinin öğeleri aynı adreslere sahip

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

original_list ve copy_list öğelerinin alt_elimleri aynı adreslere sahip

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

original_list öğelerinin değiştirilmesi, copy_list öğelerini DEĞİŞTİRMEZ

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 öğelerini değiştirmek original_list öğelerini DEĞİŞTİRMEZ

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 alt_elementlerini değiştirmek otomatik olarak copy_list alt_elementlerini değiştirir

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 alt_elementlerini değiştirmek orijinal_list alt_elementlerini otomatik olarak değiştir

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]

İkinci

hadi nasıl deepcopydavrandığımızı, copyorijinal bir liste ve bu listenin bir kopyasını oluşturarak) kontrol edelim :

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

Şimdi, bazı printtestler yapalım ve orijinal listenin kopya listesine kıyasla nasıl davrandığını görelim:

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

original_list ve copy_list'in farklı adresleri var

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

original_list ve copy_list öğelerinin öğeleri aynı adreslere sahip

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

original_list ve copy_list alt öğelerinin farklı adresleri var

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

original_list öğelerinin değiştirilmesi, copy_list öğelerini DEĞİŞTİRMEZ

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 öğelerini değiştirmek original_list öğelerini DEĞİŞTİRMEZ

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 alt_elementlerini değiştirmek copy_list alt_elementlerini DEĞİŞTİRMEZ

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 alt_elementlerini değiştirmek orijinal_list alt_elementlerini DEĞİŞTİRMEZ

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

Yukarıda bahsedilip belirtilmediğinden emin değilim, ancak .copy () 'nin orijinal nesneye referans oluşturduğunu anlamak çok önemlidir. Kopyalanan nesneyi değiştirirseniz - orijinal nesneyi değiştirirsiniz. .deepcopy () yeni nesne oluşturur ve orijinal nesnenin yenisine gerçek olarak kopyalanmasını sağlar. Yeni derin kopyalanmış nesnenin değiştirilmesi orijinal nesneyi etkilemez.

Ve evet, .deepcopy () orijinal nesneyi özyinelemeli olarak kopyalarken, .copy () orijinal nesnenin birinci düzey verilerine bir referans nesne oluşturur.

Dolayısıyla, .copy () ve .deepcopy () arasındaki kopyalama / referans farkı önemlidir.


0

Derin kopya, iç içe geçmiş yapılarla ilgilidir. Listeleriniz varsa, derin kopya iç içe listeleri de kopyalar, böylece yinelemeli bir kopyadır. Sadece kopya ile, yeni bir dış listeniz var, ancak iç listeler referanslardır. Ödev kopyalanmıyor. Ex için

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

Çıktı

[[0, 1, 2, 3, 3], 4, 5] [[0, 1, 2, 3, 3], 4, 5, 3] Dış listenin içeriğini yeni listeye kopyala, ancak iç liste her iki liste için de aynıdır, bu nedenle herhangi bir listenin iç listesinde değişiklik yaparsanız her iki listeyi de etkiler.

Ancak Derin kopya kullanırsanız, iç liste için de yeni bir örnek oluşturur.

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

Çıktı

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


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

abir derin kopyası değildir lst!
Georgy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.