์ด๋ณด์๋ก์ Python์ ์ฒ์ ์ ํ๊ฒ ๋๋ฉด '๊ฐ์ฒด ์งํฅ'์ด๋ผ๋ ๋ง์ ๋ง์ด ๋ฃ๊ฒ ๋๋ ๊ฒ ๊ฐ๋ค. ๋์ถฉ ๊ทธ๋ ๋ค๋ ๊ฒ์ ์๊ฒ ๊ณ ๐ ์ฐ์ ์์์ง๋ ๊ธฐ๋ณธ ๊ฐ๋
์ ๋ฐฐ์ฐ๋ค ๋ณด๋,
์ธ์ด์ ๊ทผ๊ฐ์ด ๋๋ ๋ถ๋ถ์ ๋์น๊ณ ์๋ ๊ฒ ๊ฐ์ ์ ๋ฆฌ๊ฐ ์ ๋ ๊ธ์ ์ฐพ์๋ณด์๋ค.
๋ณธ๋ฌธ์ ๋ค์ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ์ฌ ์์ฑํ ๊ฒ์ผ๋ก, ํ์ต ๋ชฉ์ ์ผ๋ก ๋จ์ ๋ฒ์ญํ ๊ฒ์ด๋ ์คํด ์๊ธธ ๋ฐ๋๋ค๐ก
Mutable vs Immutable Objects in Python by meghamohan on medium
Data model - object, values and types on python documentation
๊ฐ์ฒด ์งํฅ์ ์์๋ฅผ ์ฐพ๋ ์ค ์ฐ์ฐํ ์ํ ์ฝ๋ฉ ์ด๊ณ ์๋์ ์์ (๋ฌด๋ ค 7๋ ์ ) tutorial์ ๋ณด๋ฉด์ ์ข ๋ ์ดํด๊ฐ ์ฝ๊ฒ ๊ฐ๋ค. ์๋ ๊ฐ๋ ์ ๋ฆฌ์ ๋งํฌ๋ฅผ ์ฒจ๋ถํ๋ค.
์ถ์ฒ: opentutorials.org ์ด๊ณ ์
๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ํ๋ก๊ทธ๋จ ๋ก์ง์ ์ํ(state)์ ํ์(behave)๋ก ์ด๋ฃจ์ด์ง ๊ฐ์ฒด๋ก ๋ง๋๋ ๊ฒ์ด๋ค. ๊ฐ์ฒด๋ ์ฝ๊ฒ ๋งํด ๋ณ์์ ํจ์๋ฅผ ๊ทธ๋ฃจํํ ๊ฒ์ธ๋ฐ, ์ด ๊ฐ์ฒด๋ค์ ๋ ๊ณ ๋ธ๋ญ์ฒ๋ผ ์กฐ๋ฆฝํด ํ๋์ ํ๋ก๊ทธ๋จ์ผ๋ก ๋ง๋๋ ๊ฒ์ด ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ด๋ผ๊ณ ํ ์ ์๋ค. ์ปดํจํฐ์์ ์ชผ๊ฐ์ ธ ์๋ ํ์ผ์ ํด๋๋ก ๋ฌถ๋ ๊ฒ์ฒ๋ผ, ์ฐ๊ด๋์ด ์๋ ๋ณ์์ ๋ฉ์๋๋ฅผ ๊ฐ์ฒด๋ก ๊ทธ๋ฃจํํจ์ผ๋ก์จ ๊ด๋ฆฌ์ ํธ์๋ฅผ ๋๋ชจํ๋ค.
์๋ class cat์ name์ด๋ผ๋ property์ intro()๋ผ๋ ๋ฉ์๋(ํจ์)๋ฅผ ๊ฐ์ง ๊ฐ์ฒด์ด๋ฉฐ, ์ด๋ฅผ ํตํด ์ด๋ฆ๋ง ๋ฃ์ผ๋ฉด ์๊ธฐ์๊ฐ๋ฅผ ํ ์ ์๋ ๊ฐ์ฒด ์ธ์คํด์ค ๊ณ์ ๋ง๋ค ์ ์๋ค. ์๋ ์์๋ ์ง์ ๋ง๋ ๊ฒ์ผ๋ก ๋งค์ฐ ๊ฐ๋จํ์ง๋ง, ์ฌ๋ฌ ์ํ์ ํ์๋ฅผ ๊ฐ์ง ๊ฐ์ฒด๋ค์ด ์์ด๋ฉด ํ๋์ ํ๋ก๊ทธ๋จ์ด ๋ง๋ค์ด์ง ์ ์์ ๊ฒ์ด๋ค.
class cat:
def __init__(self, name):
self.name=name
def intro(self):
print('hi my name is '+self.name+ '! meow')
marble = cat('marble') # marble์ ๊ฐ์ฒด cat์ ์ธ์คํด์ค๋ก ๋ง๋ค๊ธฐ
marble.intro() # cat ํด๋์ค์ ์๊ฐ ํจ์ ํธ์ถ
์ถ์ฒ: ์ํค๋ฐฑ๊ณผ
๊ฐ์ฒด๊ฐ ๋ณ์์ ํจ์๋ฅผ ๊ทธ๋ฃจํํ ๊ฒ์ด๋ผ๊ณ ํ๋๋ฐ, ๊ทธ๋ ๋ค๋ฉด ๋ค์ ๋จ๊ณ๋ก ๋์ด๊ฐ๊ธฐ ์ ์ Python์์์ ๊ฐ์ฒด์ ๋ณ์์ ๋ํด ์์๋ณด์. ์ถ์ฒ: foobarnbaz ๋ C์ Python์ ๋ณ์ ๊ฐ๋ ๊ด๋ จ ๊ธ์ธ๋ฐ ๊ทธ๋ฆผ์ผ๋ก ์ ์ ๋ฆฌํด๋์๋ค.
C์ธ์ด์์ ๋ณ์๋ ๋ฐ์ค์ ๊ฐ๋ค. (๊ทธ๋ฆผ1) a = 2 ์ object 2๋ฅผ ๋ณ์ a์ ๋ฃ์ ๊ฒ์ด๋ค. ๋ฐ๋ฉด Python์์ ๋ณ์๋ ํ๊ทธ์ ๊ฐ๋ค. (๊ทธ๋ฆผ2) object 1์ ๋ณ์ a๋ผ๋ ํ๊ทธ๋ฅผ ๋ถ์ธ ๊ฒ์ด๋ค.
a = 2, b = a ์ผ ๋ C์ธ์ด๋ ๋ณ์๋ง๋ค ๊ฐ์ด ์ ์ฅ๋์ง๋ง, ํ์ด์ฌ์ 2๋ผ๋ ๊ฐ์ฒด์ a,b๊ฐ ํ๊ทธ๋๋ค.
๊ฐ์ฒด๋ ๋ถ๋ณ, ๊ฐ๋ณ(immutable & mutable) ์ฌ๋ถ์ ๋ฐ๋ผ ๊ตฌ๋ถ๋๊ณ , ํ์ด์ฌ์ ์ด๋ฅผ ๋ค๋ฅด๊ฒ ํธ๋ค๋งํ๋ค. ๊ทธ ๊ฐ๋ ๊ณผ ์ฐจ์ด๋ ๋ฌด์์ผ๊น?
์์1์์ int type, ์์2์์ list type์ ๋ค์ด ์ค๋ช ํด๋ณด์.
์ ์ int๋ ๋ถ๋ณ ๊ฐ์ฒด์ด๋ค. ์๋ ์ฝ๋ 3๋ฒ์งธ ์ค์์ x์ 1์ ๋ํ๋ฉด์ x๊ฐ 11์ด๋ผ๋ ๋ค๋ฅธ ๊ฐ์ฒด์ ํ๊ทธ๋๋ค. ์ฆ, ๊ฐ์ฒด 10์ ๋ฐ๋์ง ์๊ณ x๊ฐ ๋ฉ๋ชจ๋ฆฌ์์ ๊ฐ๋ฆฌํค๊ณ ์๋ id address๊ฐ ๋ฐ๋ ๊ฒ์ด๋ค.
x = 10
y = x # id(x) == id(y) == id(10)
x = x + 1
print(x) # result : 11
print(y) # result : 10
id(x) != id(y)
id(x) != id(10)
๋ฆฌ์คํธlist๋ ๊ฐ๋ณ ๊ฐ์ฒด์ด๋ค. pop method๋ฅผ ์คํํ๋ฉด์ x,y์ ๊ฐ์ฒด๊ฐ ๋ชจ๋ [1,2]๋ก ๋ฐ๋์๋ค. ๋ณ์๋ ์ฌ์ ํ ๋ฉ๋ชจ๋ฆฌ์์ ๊ฐ์ id adress๋ฅผ ๊ฐ๋ฆฌํค๊ณ , ๊ทธ ๊ฐ์ฒด๋ง ๋ฐ๋ ๊ฒ์ด๋ค.
m = [1, 2, 3]
n = m # id(m) == id(n)
m.pop() # ๋ง์ง๋ง element๋ฅผ ๋๋ ค์ฃผ๊ณ ๋ฆฌ์คํธ์์ ์ญ์ ํ๋ method
print(m) #result: [1,2]
print(n) #result: [1,2]
'''''
id(m) == id(n)
์์์ int๋ ๋ถ๋ณ ๊ฐ์ฒด, list๋ ๊ฐ๋ณ ๊ฐ์ฒด๋ผ๋ ๊ฒ์ ์๊ฒ ๋์๋ค. ๊ฐ๋ณ ๊ฐ์ฒด์ ๋ถ๋ณ ๊ฐ์ฒด๊ฐ ์ด๋ป๊ฒ ๋ค๋ฅด๋ฉฐ, int, list... ๊ทธ ์ธ์ ์ด๋ค ๋ฐ์ดํฐ ํ์ ์ด ์๋์ง ์์๋ณด๊ณ ์ ํ๋ค.
์ ์์ ์ฒ๋ผ ๋จ์ ๋ณต์ฌ(a = b
)๋ฅผ ํ๊ฒ ๋๋ฉด mutableํ ๊ธฐ์กด ๊ฐ์ฒด๊ฐ ๋ณต์ฌ๋ ๊ฐ์ฒด์ ๋์ผํ ๊ฐ์ ๊ฐ๋ฆฌ์ผ, ๊ฐ์ด ๊ฐ์ด ๋ฐ๋ ์ ์๋ค.
>>> a = [1, 2, 3]
>>> b = a
>>> b[1] = 0
>>> b
[1, 0, 3]
>>> a
[1, 0, 3]
์์ ๊ฐ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์์ ๋ณต์ฌ๋ ๊ฐ์ฒด container๋ฅผ ๋ณ๋ ์์ฑํ์ง๋ง, ๊ฐ์ฒด ๋ด๋ถ์ ๊ฐ์ฒด๋ค์ ๊ธฐ์กด ๊ฐ๊ณผ ๊ฐ๋ค. ๊ทธ๋์ ์๋์ ๊ฐ์ด item์ ์์ ํด๋ ๋ณต์ฌ๋ณธ๋ง ๋ฐ๋๊ฒ ํ ์ ์๋ค. ํ์ง๋ง ์์ ๋ณต์ฌ๋ b์ฒ๋ผ immutable ๊ฐ์ฒด์๋ง ํด๋น๋๋ฉฐ, ๋ง์ฝ c์ฒ๋ผ ๊ฐ์ฒด ๋ด๋ถ๊ฐ mutable ํ๋ค๋ฉด ๋จ์ ๋ณต์ฌ์ ๋์ผํ ํ์์ด ๋ฐ์ํ๋ค.
import copy
a = [1, [1, 2, 3]]
b = copy.copy(a) # shallow copy ๋ฐ์
print(b) # [1, [1, 2, 3]] ์ถ๋ ฅ
b[0] = 100
print(b) # [100, [1, 2, 3]]
print(a) # [1, [1, 2, 3]]
c = copy.copy(a)
c[1].append(4) # ๋ฆฌ์คํธ์ ๋๋ฒ์งธ item(๊ฐ์ฒด ๋ด๋ถ)์ 4๋ฅผ ์ถ๊ฐ
print(c) # [1, [1, 2, 3, 4]] ์ถ๋ ฅ
print(a) # [1, [1, 2, 3, 4]] ์ถ๋ ฅ
๊น์ ๋ณต์ฌ๋ ๋ด๋ถ์ ๊ฐ์ฒด๋ค๊น์ง ๋ชจ๋ ์๋กญ๊ฒ copy ๋๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์, mutableํ ๋ด๋ถ ๊ฐ์ฒด๋ฅผ ์์ ํ๋๋ผ๋ ๋ณต์ฌ๋ณธ๋ง ๋ฐ๋๊ฒ ๋๋ค.
>>> a = [[1,2],[3,4]]
>>> b = copy.deepcopy(a) # deep copy ๋ฐ์
>>> b[1].append(5) # a์ ๋ ๋ฒ์งธ item์ธ [3,4] ๋ฆฌ์คํธ์ 5 ์ถ๊ฐ
>>> a
[[1, 2], [3, 4]]
>>> b
[[1, 2], [3, 4, 5]] # ๊น์ ๋ณต์ฌ๋ก ๋ณต์ฌ๋ณธ์ ๋ด๋ถ ๊ฐ์ฒด๊น์ง ๋ณ๋ ์์ฑ
๋ฐ์ดํฐ ํ์ ์ ๋ฐ๋ฅธ ๋ถ๋ณ, ๊ฐ๋ณ ์ฌ๋ถ๋ ๋ค์๊ณผ ๊ฐ๋ค.
Mutable objects:
list, dict, set, byte array
Immutable objects:
int, float, complex, string, tuple, frozen set [note: immutable version of set], bytes
์ถ๊ฐ๋ก ๋ด์ฅ ํจ์์ธ id(), type()์ ์ฌ์ฉํด ๋ณ์๊ฐ ์ด๋ค ํ์ ์ ๊ฐ์ฒด์ ์ฐ๊ด๋์ด ์๊ณ , ๋ฐ๋ ์ ์๋ ๊ฐ์ฒด์ธ์ง๋ฅผ ํ์ธํ ์ ์๋ค.
type(5) # result: <class 'int'>
x is y #result: True
๋ง์ง๋ง์ผ๋ก ๋งค๊ฐ๋ณ์ parameter๊ฐ ํจ์๋ฅผ ํต๊ณผํ ๋์ ๋ํ์ฌ ์ ๋ฆฌํ ๋ด์ฉ์ด๋ค. ์์ง 100% ์ดํด๋์ง ์์ ์ฐธ๊ณ ํ๊ธฐ ์ข์๋งํ ์๋ฃ๋ง ์ฎ๊ฒจ๋์๋ค.
์ฐธ๊ณ : Robert Heaton & penjee blog
๋ณ์์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๊ฐ ํจ์๋ฅผ ํต๊ณผํ๋ค. ํจ์๋ฅผ ํต๊ณผํ๋ฉด ๋ณ์๋ ํจ๊ป ๋ณํ๋ค.
ํจ์์ ํ๋ผ๋ฏธํฐ ๊ฐ์ด ๋ฉ๋ชจ๋ฆฌ ๋ค๋ฅธ ๋ถ๋ถ์ ๋ณต์ฌ๋์ด, ํจ์ ๋ด๋ถ์์ ์ด ๋ณ์์ ์ ๊ทผํ๊ฑฐ๋ ๋ณ์๋ฅผ ๋ฐ๊พธ๋ ค๊ณ ํ ๋ ๋ณต์ฌ๋ณธ๋ง ์ ๊ทผ ๊ฐ๋ฅํ๋ค. ์ค๋ฆฌ์ง๋์ untouched ์ธ ์ํ์ด๊ณ , ๋ณ์๋ ๋ฆฌํด ๊ฐ์ ๋ฃ์ด์ผ ์ ๋ฐ์ดํธ ๋๋ค.