[Python] Assignment와 Shallow Copy, Deep Copy

2023. 6. 5. 23:07·Programming
728x90
728x90

시작하기 전

다음의 내용을 이해하고 보길 바람.

https://ds31x.tistory.com/404

 

[Py] 객체(object)에 대한 정보 확인하기

Python에서 object(객체)란?type, id, refcount, value 를 속성으로 가지고 있는 a chunk of data.https://dsaint31.tistory.com/517 [Python] Variable (and Object)Variable (and Object)1. 정의Python에서 Variable은 Memory에 할당된 Object

ds31x.tistory.com

https://ds31x.tistory.com/199

 

[Python] mutable and immutable: Mutability

MutabilityPython에서 Data Types를 구분짓는 중요 속성. Python에서 Object 는id,type,value,reference count를 가지는데,이 중 value를 변경할 수 있는지를 나타내는 것이 바로 mutability임. Mutable인 type의 object(객체)는

ds31x.tistory.com

is와 ==의 차이점 기억할 것:  https://ds31x.tistory.com/54

 

[Python] Boolean Operators, Relational Operators, Membership Operators and Identity Operator

https://dsaint31.tistory.com/516 -(negation) > * = / = // = % > + = -(subtraction) Lower우선순위를 기억하는 것도 중요하지만, 헷갈리면 그냥 parentheses로 묶어주면 된다. (가독성을 위해서도 " data-og-host="dsaint31.tistory

ds31x.tistory.com

 

예제 코드를 https://pythontutor.com/ 을 통해 실행해보면 보다 이해가 쉬움:

https://pythontutor.com/

 

Python Tutor - Python Online Compiler with Visual AI Help

Online Compiler, AI Tutor, and Visual Debugger for Python, Java, C, C++, and JavaScript Python Tutor helps you do programming homework assignments in Python, Java, C, C++, and JavaScript. It contains a step-by-step visual debugger and AI tutor to help you

pythontutor.com


Shallow Copy와 Deep Copy

Python에서 assignment를 수행될 때,

  • 오른쪽이 reference (즉 variable이 =연산자 우측에 있음)인 경우
  • 기본적으로 Shallow Copy가 발생한다.

하지만 특정 경우에는 Deep Copy 가 필요한 경우가 있기 때문에 이 둘의 차이를 명확히 알고 있는 것이 중요하다.

 

이 둘의 차이는 다음 그림이 간략하게 설명해 준다.

https://dev.to/edwardluu/understanding-deep-and-shallow-copy-in-javascript-4im0

Shallow copy가 일어났다면

  • 왼쪽의 경우처럼 실제 데이터가 있는 메모리영역 Referenced Object가 공유되고
  • 이를 참조하는 새로운 Cloned Object가 만들어진다.

때문에 실제로는 같은 Object를 가리키고 있기 때문에 

  • Original Object에서 수정이 일어나면
  • 해당 수정사항이 Cloned Object를 통해 접근하는 경우에도 똑같이 반영이 된다.

 

Deep copy는

  • copy가 일어나는 시점에 똑같은 값을 가지는 Object를 새로 생성하고
  • 해당 새로 생성된 Object를 가리키게 한다.

때문에 이후로는 각각의 reference가 다른 memory 영역을 가리키므로 한쪽의 수정이 다른 쪽에는 반영이 되지 않는다.

일반적으로 매우 큰 메모리를 차지하고 있는 object나
dynamic programming 등에서 사용되는 object 들은 shallow copy가 유용하지만,
값만 똑같고 다른 메모리 영역에 새로 할당을 꼭 해야 하는 경우나
원본은 보존하고 원본에 대한 복사본에서 처리를 하는 경우 등에는
deep copy가 꼭 필요하다.


immutable object에서의 copy는 일종의 copy by value에 가까움. mutable object에 대한 경우(특히 내부에 또 mutable object 를 가지고 있을 때)에는 shallow copy와 deep copy를 구분해야함.

Assignment=같은 object를 가리킴, Copy Constructor=Mutability에 따라 다름.

Python에서 assignment는

  • 왼쪽 variable (or name, reference)이 오른쪽에 놓인 value(or Object)를 참조하도록 하는 것으로
  • 오른쪽 expression의 최종값을 value로 가지는 Object를 왼쪽의 variable이 가리키도록(refer to) 할당(=해당 object를 참조).

2023.06.13 - [Programming] - [Python] Variable (and Object)

 

[Python] Variable (and Object)

Python에서 Variable은 Memory에 할당된 Ojbect를 참조하는 Name (=Reference)에 불과하다. 이 문서에서 Object는 Python에서의 Object로 type과 value, ID (CPython에서는 할당된 memory address), 그리고 reference count를 가지

dsaint31.tistory.com

즉, variable(or reference)이 assignment에서 오른쪽 operand인 경우,
왼쪽 operand인 variable(or reference)도 같은 object를 참조하게 된다.


immutable object에 대한 variable 이 우측 operand인 경우.

다음 예제 코드는 오른쪽 operand인 variaible이 immutable object를 참조하는 경우이며 d0 와 d1 가 가리키는 object들이 같은 ID를 가지게 됨(=같은 Object 참조)

# 단순 assignment는 같은 object를 가리킴.
d0 = (1,2,3)
d1 = d0
print(f'id of d0:{id(d0)}, id of d1:{id(d1)}')

결과는 다음과 같음.

id of d0:140488388961920, id of d1:140488388961920
d1 is d0 : True
d1 == d0 : True

tuple은 immutable.

 

주의할 것은 immutable object의 copy constructor를 assignment의 오른쪽 operand로 놓은 경우도 같은 object를 가리키게 된다는 점이다. (생성을 하는 것처럼 보이지만... 변경불가의 object를 굳이 다시 만들 필요가 없으므로)

d2 = tuple(d0)
print(f'id of d2:{id(d2)}')
print(f'd1 is d0 : {d1 is d0}')
print(f'd1 == d0 : {d1 == d0}')

결과는 다음과 같음.

id of d2:140488388961920
d1 is d0 : True
d1 == d0 : True

mutable object에 대한 variable 이 우측 operand인 경우.

Mutable의 경우도 단순 assignment는 같은 memory 영역을 가리킴 (Variable은 단순 reference임을 잊지 말자).

# Muutable obj.는 shallow copy!
d0 = [1,2,3]
d1 = d0
print(f'id of d0:{id(d0)}, id of d1:{id(d1)}')
print(f'd1 is d0 : {d1 is d0}')
print(f'd1 == d0 : {d1 == d0}')

결과는 다음과 같음.

id of d0:140489189478208, id of d1:140489189478208
d1 is d0 : True
d1 == d0 : True

 

단, immutable의 경우와 달리 mutable object에 대한 variable을 이용한 copy constructor에서는 새로 memory할당이 된 object를 가리키게 된다.

d2 = list(d0)
print(f'id of d2:{id(d2)}')
print(f'd1 is d0 : {d2 is d0}')
print(f'd1 == d0 : {d2 == d0}')

결과

id of d2:140650393264576
d1 is d0 : False
d1 == d0 : True

[:] slicing을 이용한 경우

immutable의 경우엔 단순히 assignment 한 것과 같은 결과 이지만, mutable인 경우엔 다른 메모리 영역에 새로 할당 이 이루어진다.

주의할 것은 deep copy는 아니라는 점임.

immutable의 경우

d0 = ([1,2,3],1,2,3) #Immutable
d1 = d0[:]
print(f'id of d0:{id(d0)}, id of d1:{id(d1)}')
print(f'd1 is d0 : {d1 is d0}')
print(f'd1 == d0 : {d1 == d0}')

결과

id of d0:140488387426592, id of d1:140488387426592
d1 is d0 : True
d1 == d0 : True

mutable의 경우

d0 = [[1,2,3],1,2,3] # mutable
d1 = d0[:]
print(f'id of d0:{id(d0)}, id of d1:{id(d1)}')
print(f'd1 is d0 : {d1 is d0}')
print(f'd1 == d0 : {d1 == d0}')

결과

id of d0:140488387495104, id of d1:140488387053504
d1 is d0 : False
d1 == d0 : True

 

주의할 것은 item이 list와 같은 mutable collection인 경우 item 들이 새로 만들어지는 것은 아니라는 점이다.

d0 = [[1,2,3],1,2,3]
d1 = d0[:]
d1[0][0] = 777
print(f'd0:{d0}\nd1:{d1}')

결과

d0:[[777, 2, 3], 1, 2, 3]
d1:[[777, 2, 3], 1, 2, 3]

 

앞서 본 것처럼 d0 와 d1 은 다른 메모리 영역(list를 위해 할당된)을 가리키나,

해당 list의 index 0인 item이 mutable인 [1,2,3] list이며 이는 d0와 d1이 공유하고 있다.

때문에 한 쪽을 수정할 경우 다른 쪽에도 영향을 주어 777로 바뀐 것을 볼 수 있음.

 

즉, shallow copy가 이루어진 것임.

만약 item이 immutable collection이라면?

immutable collection은 수정이 안되기 때문에 변경이 이루어지면 그냥 새로 생성하여 할당이 된다. 때문에 shallow copy이지만 마치 deep copy처럼 변경된 것으로 보일 수 있으나, 해당 item에 처리가 이루어질 때 아예 다른 object가 만들어져서 재할당된 것이지 앞서의 assignment에서 deep copy가 된 건 아님.

d0 = [(1,2,3),1,2,3]
d1 = d0[:] # 이 시점까지 shallow copy로 ,d0와 d1모두 같은 (1,2,3) object를 가르킴.
print (d0[0] is d1[0])
d1[0] += (4,5) # tuple에 대한 augmented assignment는 새로운 object를 생성하고 재할당임.
print (d0[0] is d1[0])
print(f'd0:{d0}\nd1:{d1}')

결과는 다음과 같음.

True
False
d0:[(1, 2, 3), 1, 2, 3]
d1:[(1, 2, 3, 4, 5), 1, 2, 3]

copy 메서드를 이용한 경우 (=shallow copy)

immutable object들에서는 copy메소드가 지원되지 않으며, mutable object에서만 지원함.

 

기본적으로 새로운 메모리 영역을 할당하지만, item으로 있는 mutable object들은 공유를 하기 때문에 shallow copy임.

 

위의 그림에서 왼쪽에 해당하며,bag0에 대해 shallow copy를 수행한 bag1 경우처럼 item들은 새로 만들어지는 것이 아니다.

a = [[1,2,3],'test']
b = a.copy() 

print(f'a is b:{a is b}')
b[0][0]=77
print(f'a is {a}\nb is {b}')

결과는 다음과 같음

a is b:False
a is [[77, 2, 3], 'test']
b is [[77, 2, 3], 'test']

deep copy : copy 모듈의 deepcopy() 함수

mutable object가 item인 collection 객체들에 대해 deep copy를 하기 위해선 copy모듈의 deepcopy 함수를 사용한다.

 

다음 예제 코드를 참고하라.

import copy

a = [[1,2,3],'test']
c = copy.deepcopy(a)
c[0][0] = 77
print(f'a is {a}\nb is {c}')

결과는 다음과 같다

a is [[1, 2, 3], 'test']
b is [[77, 2, 3], 'test']

literal의 경우

기본적으로 literal로 할당하는 경우는 다른 객체를 가리키게 된다(값이 같더라도...)

 

하지만, Python의 경우 memory의 효율적 사용을 위해서

literal 및 constant 등에 대해선 copy constructor와 같이 동일한 memory 영역을 가리키는 형태로 처리함:

 

작은 정수 (-5~256) 이거나 특정 규칙을 따르는 짧은 문자열의 경우 PVM이 미리 생성하여 캐싱.

  • [-5,256] 범위의 정수에 대한 이같은 처리를 integer caching이라고 부름.
  • 특정 규칙을 따르는 문자열을 resue하는 처리는 Automate String Interning이라고 부름(아래 url참고)

 

literal이란:

2023.02.20 - [Programming] - [Basic] Literal

 

[Basic] Literal

Literal소스 코드 상에서 고정된 값을 가르킴. (또는 고정된 값을 나타내는 표기법을 의미함.)Programming language에서 data의 값을 지정(specifying data values)하는 방법은 다음 중의 하나임.1. Literal을 사용.2

dsaint31.tistory.com

String Interning이란?
https://ds31x.tistory.com/472

 

[Py] String Interning

Intern(인터닝)은 Python에서 문자열 최적화 기법의 하나로서,동일한 문자열을 메모리에 한 번만 저장하고 여러 변수가 같은 객체를 참조하도록 하는 기법을 가리킴.# Normal case (not interned)a = "hello wor

ds31x.tistory.com

 

다음 예제 코드를 참고하라.

a = 7
b = 7
print(f'a is b: {a is b}')

c = b
print(f'c is a: {c is a}')

결과는 다음과 같음.

a is b: True
c is a: True

memory의 효율적 사용을 위해서 많이 사용되는 일부 literal 및 copy constructor에선 shallow copy와 같이 같은 memory의 영역을 가리키게 됨.

 

물론 명시적으로 다음과 같이 값만 같은 tuple을 따로 할당 하면 다른 memory 영역에 생성 됨 

(integer caching 및 automatic string interning 을 제외하고, literal로 명시적 할당은 다른 객체를 가리키게 됨.)

a = (1,2)
b = (1,2)

print( f'a is b :{a is b} / a == b : {a ==b}')

결과

a is b :False / a == b : True

같이보면 좋은 자료

https://ds31x.tistory.com/194

 

[Python] Arithmetic, Variables, Types and Assignment

Numeric Type and Arithmetic in Python (+Augmented Assignment)https://dsaint31.tistory.com/516 -(negation) > * = / = // = % > + = -(subtraction) Lower우선순위를 기억하는 것도 중요하지만, 헷갈리면 그냥 parentheses로 묶어주면 된다

ds31x.tistory.com


 

'Programming' 카테고리의 다른 글

[Python] Iterable and Iterator, plus Generator  (1) 2023.06.07
[Python] Comprehension (list, dict, set) and Generator Expression  (0) 2023.06.06
[Programming] Garbage Collection (GC)  (0) 2023.06.05
[Python] Interpreter and PVM (Python Virtual Machine)  (2) 2023.06.05
[Python] recursive call : Fibonacci Sequence (and dynamic programming)  (0) 2023.05.24
'Programming' 카테고리의 다른 글
  • [Python] Iterable and Iterator, plus Generator
  • [Python] Comprehension (list, dict, set) and Generator Expression
  • [Programming] Garbage Collection (GC)
  • [Python] Interpreter and PVM (Python Virtual Machine)
dsaint31x
dsaint31x
    반응형
    250x250
  • dsaint31x
    Dsaint31's blog
    dsaint31x
  • 전체
    오늘
    어제
    • 분류 전체보기 (770)
      • Private Life (13)
      • Programming (200)
        • DIP (116)
        • ML (28)
      • Computer (119)
        • CE (53)
        • ETC (33)
        • CUDA (3)
        • Blog, Markdown, Latex (4)
        • Linux (9)
      • ... (362)
        • Signals and Systems (110)
        • Math (175)
        • Linear Algebra (33)
        • Physics (43)
        • 인성세미나 (1)
      • 정리필요. (59)
        • 의료기기의 이해 (6)
        • PET, MRI and so on. (5)
        • PET Study 2009 (1)
        • 방사선 장해방호 (5)
        • 방사선 생물학 (3)
        • 방사선 계측 (9)
        • 기타 방사능관련 (3)
        • 고시 (9)
        • 정리 (18)
      • RI (0)
      • 원자력,방사능 관련법 (2)
  • 블로그 메뉴

    • Math
    • Programming
    • SS
    • DIP
  • 링크

    • Convex Optimization For All
  • 공지사항

    • Test
    • PET Study 2009
    • 기타 방사능관련.
  • 인기 글

  • 태그

    Probability
    Term
    linear algebra
    Python
    fourier transform
    Vector
    SIGNAL
    numpy
    SS
    Optimization
    cv2
    function
    Programming
    random
    math
    opencv
    signal_and_system
    signals_and_systems
    Convolution
    인허가제도
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
dsaint31x
[Python] Assignment와 Shallow Copy, Deep Copy
상단으로

티스토리툴바