ํŒŒ์ด์ฌ ๊นŠ์€ ๋ณต์‚ฌ, ์–•์€ ๋ณต์‚ฌ (shallow copy, deep copy)

2021. 5. 18. 02:46ใ†Backend/๐Ÿ Python

ํŒŒ์ด์ฌ ๊ฐ์ฒด ๋ณต์‚ฌ

  • ๊ฐ์ฒด์˜ ๋ณต์‚ฌ ์ข…๋ฅ˜: copy, shallow copy, deep copy

์ผ๋ฐ˜ ๋ณต์‚ฌ, copy

  • ์›๋ณธ ๊ฐ์ฒด์˜ ์ฐธ์กฐ๊ฐ’๊นŒ์ง€ ๋ณต์‚ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ณต์‚ฌ๋œ ๊ฐ์ฒด์˜ ์›์†Œ๊ฐ€ ๋‹ฌ๋ผ์ง€๋ฉด ์›๋ณธ ๊ฐ์ฒด๋„ ๋‹ฌ๋ผ์ง„๋‹ค.
  • ํŠน๋ณ„ํ•œ ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ์ด ์•„๋‹Œ, ๊ทธ์ € ๊ฐ์ฒดํ• ๋‹น์œผ๋กœ ๋ณต์‚ฌ.
# Ex 1 - Copy
# call by value, call by refference, call by share

a_list = [1, 2, 3, [4, 5, 6], [7, 8, 9]]
b_list = a_list

print('Ex 1 > ', id(a_list))
print('Ex 1 > ', id(b_list))  # b_list ๋Š” a_list ๋ฅผ ํ• ๋‹น๋ฐ›๊ธฐ ๋•Œ๋ฌธ์—
# ๊ฐ™์€ ์ฃผ์†Œ ์ฐธ์กฐ์ž„์„ ํ™•์ธ ๊ฐ€๋Šฅ
>>> Ex 1 >  4384525248
>>> Ex 1 >  4384525248


b_list[2] = 100
print('Ex 1 > ', id(a_list), a_list)  # b_list[2] ์— ํ• ๋‹นํ–ˆ๋Š”๋ฐ, a_list ๋„ ๋ณ€๊ฒฝ๋œ๋‹ค.
print('Ex 1 > ', id(b_list), b_list)
# ์—ฌ์ „ํžˆ ๊ฐ™๋‹ค => call by reference

>>> Ex 1 >  4384525248 [1, 2, 100, [4, 5, 6], [7, 8, 9]]
>>> Ex 1 >  4384525248 [1, 2, 100, [4, 5, 6], [7, 8, 9]]

์–•์€ ๋ณต์‚ฌ, shallow copy

  • ์ผ๋ฐ˜ copy์™€ ๋‹ฌ๋ฆฌ, copy ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž„ํฌํŠธ ํ›„์—, copy.copy() ๋ฉ”์„œ๋“œ๋กœ ๋ณต์‚ฌํ•œ๋‹ค.
  • shallow copy๋Š” ์›๋ณธ ๊ฐ์ฒด์™€ ๋‹ค๋ฅธ ์ฐธ์กฐ๊ฐ’์„ ์ƒ์„ฑํ•œ๋‹ค. (์ผ๋ฐ˜ copy๋Š” ์›๋ณธ ๊ฐ์ฒด์™€ ๊ฐ™์€ ์ฐธ์กฐ๊ฐ’ ์ƒ์„ฑ)
# Ex 2 - Shallow Copy: ์–•์€ ๋ณต์‚ฌ
import copy
c_list = [1, 2, 3, [4, 5, 6], [7, 8, 9]]
d_list = copy.copy(c_list)
print('Ex 2 > ', id(c_list)) # Ex 2 >  4384526976
print('Ex 2 > ', id(d_list)) # Ex 2 >  4384527424

# ์ฐธ์กฐํ˜•์˜ ์ฃผ์†Œ๊ฐ’์„ ๊ณต์œ ํ•˜๋˜ ์ด์ „๊ณผ๋Š” ๋‹ฌ๋ฆฌ, ์ง€๊ธˆ์€ ์ฃผ์†Œ๊ฐ’์ด ๋‹ค๋ฅด๋‹ค.
# ์ด ๋ฐฉ๋ฒ•์€ ์–ด๋Š ๊ฐ์ฒด์˜ ์‚ฌ๋ณธ์„ ๋งŒ๋“ฆ์œผ๋กœ, ๋ณธ ๊ฐ์ฒด๋ฅผ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๊ณ  ์‚ฌ๋ณธ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

d_list[1] = 100
print('Ex 2 > ', (c_list))  # Ex 2 >  [1, 2, 3, [4, 5, 6], [7, 8, 9]]
print('Ex 2 > ', (d_list))  # Ex 2 >  [1, 100, 3, [4, 5, 6], [7, 8, 9]]
# d_list์—๋งŒ 100 ๋“ค์–ด๊ฐ

d_list[3].append(1000)
d_list[4][1] = 10000
print('Ex 2 > ', (c_list))  # Ex 2 >  [1, 2, 3, [4, 5, 6, 1000], [7, 10000, 9]]

print('Ex 2 > ', (d_list))  # Ex 2 >  [1, 100, 3, [4, 5, 6, 1000], [7, 10000, 9]]

# ์–•์€ ๋ณต์‚ฌ์ด๊ธฐ ๋•Œ๋ฌธ์—, ์ค‘์ฒฉ๋œ ๊ฐ์ฒด์— ๋Œ€ํ•ด์„œ ์›๋ณต ๊ฐ์ฒด๋„ ๊ทธ๋Œ€๋กœ ๋ณ€๊ฒฝ์ด ์ผ์–ด๋‚ฌ๋‹ค.(์›๋ณธ์„ ์ง€ํ‚ค์ง€ ๋ชปํ•จ: ์›๋ณธ์˜ ์˜๋ฏธ๊ฐ€ ์—†๋‹ค)
# ์–•์€ ๋ณต์‚ฌ๋Š” ์„ธ๋ถ€ ๊ฐ์ฒด๊นŒ์ง€ ๋ณต์‚ฌํ•˜์ง€ ๋ชปํ•œ๋‹ค : call by reference

์ •๋ฆฌ

1) ์–•์€ ๋ณต์‚ฌ - copy.copy(๊ฐ์ฒด) ์— ๋Œ€ํ•ด 1์ฐจ ๋ฐฐ์—ด(๋ฆฌ์ŠคํŠธ)๋Š” ์›๋ณธ ๊ฐ์ฒด๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ค์ง€ ์•Š๋Š” ์‚ฌ๋ณธ์„ ์ƒ์„ฑํ•ด๋‚ธ๋‹ค.
2) ๋ฌธ์ œ: 2์ฐจ ์ด์ƒ์˜ ๋ฐฐ์—ด, ์ค‘์ฒฉ๋œ ๊ฐ์ฒด๋Š” ์›๋ณธ๊ฐ์ฒด๋ฅผ ์ง€ํ‚ค์ง€ ๋ชปํ•œ๋‹ค. ์ฆ‰ ์™„๋ฒฝํ•œ ๊ฐ์ฒด ๋ณต์‚ฌ๋ฅผ ํ•˜์ง€ ๋ชปํ•œ๋‹ค.


๊นŠ์€ ๋ณต์‚ฌ, deep copy

  • shallow copy๋Š” ์ค‘์ฒฉ ๊ฐ์ฒด(ex 2์ฐจ ์ด์ƒ์˜ ๋ฆฌ์ŠคํŠธ)์˜ ์˜์—ญ๊นŒ์ง€ ๋ณต์‚ฌ๋ฅผ ํ•˜์ง€ ๋ชปํ•œ๋‹ค. (๊ทธ๋ž˜์„œ shallow copy)
  • ๊นŠ์€ ๋ณต์‚ฌ๋Š” ์ด๋Ÿฐ ํ•œ๊ณ„์ ์„ ๋„˜์–ด ์ค‘์ฒฉ ๊ฐ์ฒด์— ๋Œ€ํ•ด์„œ๋„ ์™„๋ฒฝํžˆ ๋ณต์‚ฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • copy.deepcopy() ๋ฉ”์†Œ๋“œ ์‚ฌ์šฉ.

# Ex 3 - Deep Copy : ๊นŠ์€ ๋ณต์‚ฌ
e_list = [1, 2, 3, [4, 5, 6], [7, 8, 9]]
f_list = copy.deepcopy(e_list)  # ์–•์€ ๋ณต์‚ฌ๋Š” copy.copy() <--> ๊นŠ์€ ๋ณต์‚ฌ๋Š” copy.deepcopy()

f_list[3].append(1000)
f_list[4][1] = 10000

print('Ex3 > ', id(e_list), e_list)  # Ex3 > 4309846592 [1, 2, 3, [4, 5, 6], [7, 8, 9]]
print('Ex3 > ', id(f_list), f_list) # Ex3 > 4308765632 [1, 2, 3, [4, 5, 6, 1000], [7, 10000, 9]]

# ์šฐ์„  ์„œ๋กœ๋‹ค๋ฅธ ์ฃผ์†Œ๊ฐ’ ์ฐธ์กฐ
# f_list ์™€ e_list ๋Š” ๋‹ค๋ฅธ ํ˜•ํƒœ๋ฅผ ๊ฐ–๊ฒŒ ๋œ๋‹ค. ๊นŠ์€ ์š”์†Œ๊นŒ์ง€ ๋ณต์‚ฌํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ „์ฒด ์ •๋ฆฌ

  • ๊ทธ๋ ‡๋‹ค๋ฉด ์™œ ๋Š˜ deepcopy๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋ ๊นŒ? (shallow copy๋ณด๋‹ค ๋งŒ๋Šฅ์ฒ˜๋Ÿผ ๋ณด์ด๋Š”๋ฐ)
  • ์šฐ์„  ๋ฉ”๋ชจ๋ฆฌ ์†Œ์š”.
    ๋งŒ์•ฝ 1์–ต๊ฐœ์˜ ์›์†Œ ์ง€๋‹Œ ๋ฆฌ์ŠคํŠธ๋ฅผ deepcopy ํ•œ๋‹ค๋ฉด ๋ฉ”๋ชจ๋ฆฌ ์†Œ์š”๊ฐ€ ์‹ฌํ•ด์ง„๋‹ค.
    ์ƒํ™ฉ์„ ๊ณ ๋ คํ•˜์—ฌ shallow copy ํ•  ๊ฒƒ์ธ์ง€ deep copy ํ•  ๊ฒƒ์ธ์ง€ ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ฒฐ์ •ํ•œ๋‹ค.