programing

dict.copy() 이해 - 얕은가 깊은가?

sourcetip 2023. 1. 10. 21:35
반응형

dict.copy() 이해 - 얕은가 깊은가?

에 대한 문서를 읽는 동안dict.copy(), 그것은 사전의 얕은 복사본을 만든다고 말한다.내가 팔로우하고 있는 책(Beazley's Python Reference)도 마찬가지다.

m.copy() 메서드는 매핑 객체에 포함된 항목의 얕은 복사본을 만들어 새 매핑 객체에 배치합니다.

다음 사항을 고려하십시오.

>>> original = dict(a=1, b=2)
>>> new = original.copy()
>>> new.update({'c': 3})
>>> original
{'a': 1, 'b': 2}
>>> new
{'a': 1, 'c': 3, 'b': 2}

그래서 나는 이것이 새로운 가치를 만들어 낼 것이라고 생각했다.original(그리고 'c'를 더하면 3) 저도 얕은 복사를 하고 있었거든요.예를 들어 목록에 대해 수행하는 경우:

>>> original = [1, 2, 3]
>>> new = original
>>> new.append(4)
>>> new, original
([1, 2, 3, 4], [1, 2, 3, 4])

이것은 예상대로 동작합니다.

둘 다 얄팍한 복사품이기 때문에, 왜 그게dict.copy()내가 기대한 대로 되지 않는가?아니면 얕은 복사와 깊은 복사에 대한 이해가 부족합니까?

"복사 허용"은 사전의 내용이 값별로 복사되는 것이 아니라 새 참조를 만드는 것을 의미합니다.

>>> a = {1: [1,2,3]}
>>> b = a.copy()
>>> a, b
({1: [1, 2, 3]}, {1: [1, 2, 3]})
>>> a[1].append(4)
>>> a, b
({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})

반면 딥 카피는 모든 콘텐츠를 값별로 복사합니다.

>>> import copy
>>> c = copy.deepcopy(a)
>>> a, c
({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
>>> a[1].append(5)
>>> a, c
({1: [1, 2, 3, 4, 5]}, {1: [1, 2, 3, 4]})

그래서:

  1. b = a: 레퍼런스 할당, 작성a그리고.b같은 객체를 가리킵니다.

    그림 'a = b': 'a' 및 'b'는 모두 '{1: L}', 'L'은 '[1, 2, 3]'을 가리킵니다.

  2. b = a.copy(): 얕은 복사,a그리고.b두 개의 분리된 객체가 되지만 그 내용은 여전히 동일한 참조를 공유합니다.

    'b = a.copy()'의 그림: 'a'는 '{1: L}', 'b'는 '{1: M}', 'L', 'M' 모두 '[1, 2, 3]'을 가리킵니다.

  3. b = copy.deepcopy(a): 딥 카피,a그리고.b의 구조와 내용은 완전히 격리됩니다.

    그림 'b = copy.deepcopy(a)': 'a'는 '{1: L}', 'L'은 '[1, 2, 3]', 'b'는 '{1: M}', 'M'은 '[1, 2, 3]'의 다른 인스턴스를 가리킵니다.

다음 예를 들어보겠습니다.

original = dict(a=1, b=2, c=dict(d=4, e=5))
new = original.copy()

이제 'shallow'(첫 번째) 수준의 값을 변경합니다.

new['a'] = 10
# new = {'a': 10, 'b': 2, 'c': {'d': 4, 'e': 5}}
# original = {'a': 1, 'b': 2, 'c': {'d': 4, 'e': 5}}
# no change in original, since ['a'] is an immutable integer

이제 값을 한 단계 더 깊이 변경해 보겠습니다.

new['c']['d'] = 40
# new = {'a': 10, 'b': 2, 'c': {'d': 40, 'e': 5}}
# original = {'a': 1, 'b': 2, 'c': {'d': 40, 'e': 5}}
# new['c'] points to the same original['d'] mutable dictionary, so it will be changed

딥 카피나 얄팍한 카피의 문제가 아니라, 딥 카피의 문제가 아닙니다.

여기:

>>> new = original 

원본에서 참조하는 목록/목록에 대한 새 참조를 만듭니다.

여기 있는 동안:

>>> new = original.copy()
>>> # or
>>> new = list(original) # dict(original)

원래 컨테이너에 포함된 객체의 참조 복사본으로 채워진 새 목록/목록을 만듭니다.

kennytm의 답변에 추가.얕은 copy parent.copy()를 실행하면 동일한 키로 새 사전이 생성되지만 값은 복사되지 않고 참조됩니다.parent_copy에 새 값을 추가해도 parent_copy는 참조가 아닌 새 사전이기 때문에 부모에 영향을 주지 않습니다.

parent = {1: [1,2,3]}
parent_copy = parent.copy()
parent_reference = parent

print id(parent),id(parent_copy),id(parent_reference)
#140690938288400 140690938290536 140690938288400

print id(parent[1]),id(parent_copy[1]),id(parent_reference[1])
#140690938137128 140690938137128 140690938137128

parent_copy[1].append(4)
parent_copy[2] = ['new']

print parent, parent_copy, parent_reference
#{1: [1, 2, 3, 4]} {1: [1, 2, 3, 4], 2: ['new']} {1: [1, 2, 3, 4]}

parent[1], parent_copy[1]의 해시(id) 값은 ID 140690938288400에 저장된 parent[1]parent_copy[1]의 [1,2,3]를 의미합니다.

그러나 parent_copy와 parent_copy해시는 다르며, 이는 서로 다른 사전이며 parent_copy는 부모의 을 참조하는 값을 가진 새로운 사전임을 의미합니다.

"new"와 "original"은 서로 다른 명령어이므로 그 중 하나만 업데이트할 수 있습니다.항목은 dict 자체가 아니라 얄팍하게 복사되어 있습니다.

내용이 얕게 복사되었습니다.

만약 원본이dict에는 를 contains contains a a가 되어 있습니다.list 다른 느느 or or ordictionarylist ★★★dict을 클릭합니다.

에서는 '어울리다'를 요.new = original.copy()

.copy ★★★★★★★★★★★★★★★★★」=른른른것것것다

언급URL : https://stackoverflow.com/questions/3975376/understanding-dict-copy-shallow-or-deep

반응형