- Managed Language๋ ์ฌ์ฉ์๊ฐ ์ผ๋ถ๋ฌ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ๋ฐ ํด์ ๋ฅผ ํ์ง ์์๋ ๋๋ ์ธ์ด๋ฅผ ๋ปํ๋ค. ๋ํ์ ์ผ๋ก JAVA, Python์ด ์๋ค.
- Unmanaged language๋ ๊ทธ ๋ฐ๋๋ก ๋ํ์ ์ผ๋ก C๊ฐ ์๋ค.
C๋ก ํ๋ก์ ํธ๋ฅผ 4๊ฐ๋ฅผ ํ๋ค. ํนํ, ๊ทธ์ค malloc lab๊น์ง ํ์๋ค. ๋ฉ๋ชจ๋ฆฌ ํ ๋น๊ณผ ํด์ ์ ๋ํด์ ๊น๊นํ ํด์ผํ๋ C๋ฅผ ํ๋ ์ ์ฅ์ผ๋ก python์ ์ด๋ป๊ฒ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๊ด๋ฆฌ๋๋์ง ๊ถ๊ธํ๋ค.
a = 1000
1 . 1000์ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์์ ๋ด๋๋ค. 2 . a๋ผ๋ ๋ณ์๋ ๊ทธ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ์ฐธ์กฐํ๋ค.
In[1] : a = 1000
In[2] : print(hex(id(a)))
Out[1] : 0x7fee093b9c70
0x7fee093b9c70 ์ฃผ์๋ฅผ ์ฐธ์กฐํจ์ ์ ์ ์๋ค.
id(a)
id(obj)๋ ํด๋น ๊ฐ์ฒด / ๋ณ์์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๊ฐ์ ๋ฐํํ๋ ํจ์์ด๋ค. C์์ & ํฌ์ธํฐ ์ฐ์ฐ์์ ๋์ผํ๋ค. ๊ทธ๋ผ ๋น๊ต ํด๋ด์ผ์ง.
char chr = 'a';
printf("%x", &chr);
hex(id('a')) # hex๋ 16์ง์๋ก ๋ฐ๊พธ์ด์ฃผ๋ ํจ์์ด๋ค.
์ ๋๊ฐ์ง๋ ๋์ผํ ์ญํ ์ ํ๋ ํจ์์ด๋ค.
1๋ฒ ์์
In[1] : a = [1,2,3]
In[2] : b = [1,2,3]
In[3] : print(a is b)
Out[1] : False
In[4] : print(a == b)
Out[1] : True
2๋ฒ ์์
In[1] : a = [1,2,3]
In[2] : b = a
In[3] : print(a is b)
Out[1] : True
In[4] : print(a == b)
Out[1] : True
์์๋ฅผ ๋ณด๋ฉด ์ ์ ์๋ฏ์ด ==์ ๊ฐ์ ๋น๊ตํ๋ ๋น๊ต์ฐ์ฐ์์ธ ๋ฐ๋ฉด์ is๋ ์ฃผ์๊ฐ์ ๋น๊ตํ๋ ๋น๊ต์ฐ์ฐ์์์ ์ ์ ์๋ค. ๋ฐ๋ผ์ == ์ฐ์ฐ์๋ ํด๋น ๊ฐ์ ์ฐพ๊ณ ๊ทธ ๊ฐ์ ๋น๊ตํ๋ ์ฐ์ฐ๊ณผ์ ์ด ์๊ณ is ๋ ๋ฐ๋ก ์ฃผ์๊ฐ์ ๋น๊ตํ๊ธฐ๋๋ฌธ์ is ๊ฐ ==์ ๋นํด ์ฝ๊ฐ ๋ ๋น ๋ฅด๋ค.
mutableํ์ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๊ฐ์ฒด์ด๋ค. ๊ฐ์ฒด ๊ฐ์ด ๋ณ๊ฒฝ๋๋๋ผ๋ ๋ฉ๋ชจ๋ฆฌ์ ์ฌํ ๋น์ด ์ผ์ด๋์ง ์๋๋ค. ์๋ก set, list, dict ๋ฑ์ด ์๋ค.
In[1] : mutable1 = ['alpha'] # list
In[2] : print(hex(id(mutable1)))
Out[1] : 0x7f9cee27eb40
In[3] : mutable1.append('bravo')
In[4] : print(hex(id(mutable1)))
Out[2] : 0x7f9cee27eb40 # ์ฃผ์๊ฐ์ด ๊ฐ๋ค
immutableํ์ ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅํ ๊ฐ์ฒด๋ก ๊ฐ์ฒด๊ฐ ๋ณ๊ฒฝ ์ ๋ฉ๋ชจ๋ฆฌ์์ ์ฌํ ๋น์ด ์ผ์ด๋๋ค. ์๋ก int, float, string ๋ฑ ๋๋ถ๋ถ ์์ ์๋ฃํ๋ค์ด ์ํ๋ค.
In[1] : immutable1 = 1000 # int
In[2] : print(hex(id(immutable1)))
Out[1] : 0x7fc68f2a2c50
In[3] : immutable1 += 1
In[4] : print(hex(id(immutable1)))
Out[1] : 0x7fc68f2a2d10
In[1] : a = 1000
In[2] : b = a
In[3] : print(a is b)
Out[1] : True
In[4] : b += 1
In[5] : print(a, b, a is b)
Out[2] : 1000 1001 False
a๋ b์ ๊ฐ์ ์ฃผ์๊ฐ์ ์ฐธ์กฐํ๊ณ ์์์ง๋ง immutable ํ์ธ Intํ b์ 1์ ๋ํจ์ผ๋ก์ ๋ฉ๋ชจ๋ฆฌ ์ฌํ ๋น์ด ์ผ์ด๋ฌ๊ณ b์ ์ฃผ์๊ฐ์ด ๋ฐ๋์ด out[2]์์๋ False๊ฐ ๋์ด์ ์ ์ ์๋ค.
In[1] : a = ['Mon', 'Tue']
In[2] : b = a
In[3] : b.append('Wed')
In[4] : print(a, b, a is b)
Out[1] : ['Mon', 'Tue', 'Wed'] ['Mon', 'Tue', 'Wed'] True
b์๋ง 'Wed' element๋ฅผ ๋ํ๋๋ฐ a์๋ ๋ํด์ ธ์๋ค. mutableํ์ธ list a์ b๋ ์๋ก ๊ฐ์ ์ฃผ์๊ฐ์ ์ฐธ์กฐํ๊ณ ์๊ธฐ๋๋ฌธ์ ์๋ก ์ข ์๋ ๊ด๊ณ๋ฅผ ๊ฐ๋๋ค.
์ด๋ฏธ ๊ธ์ ์ฌ๋ฆฐ ์ ์ด ์์ง๋ง ํด๋น ๊ธ์ ์ค๋ช ์ ์ํด ํ๋ฒ ๋ ์ค๋ช ํ๋๋ก ํ๋ค. ์ด์ ๊ธ์์ python clone, copy ๋ณด๋ฌ๊ฐ๊ธฐ
In[1] : a = ['Mon', 'Tue']
In[2] : b = a[:]
In[3] : b.append('Wed')
In[4] : print(a, b, a is b)
Out[1] : ['Mon', 'Tue'] ['Mon', 'Tue', 'Wed'] False
slice๋ฅผ ํ๋ ๋ฐฉ๋ฒ์ผ๋ก ์ฝ๊ฒ ํด๊ฒฐํ๋ค.
In[1] : a = ['Mon', 'Tue']
In[2] : b = a.copy()
In[3] : b.append('Wed')
In[4] : print(a, b, a is b)
Out[1] : ['Mon', 'Tue'] ['Mon', 'Tue', 'Wed'] False
copy ํจ์๋ฅผ ์ฌ์ฉํด์ ํด๊ฒฐํ๋ค.
In[1] : a = ['Head', ['Sub']]
In[2] : b = a.copy() # or a[:]
In[3] : b[1].append('Sub2')
In[4] : print(a, b)
Out[1] : ['Head', ['Sub', 'Sub2']] ['Head', ['Sub', 'Sub2']]
list์์ list (nested list)๋ ์์ ํ copy๊ฐ ๋์ง ์์์์ ์ ์ ์๋ค. slice์ copy์ ์๋์๋ฆฌ๋ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ (์๋ก์ด ์ฃผ์์) element์ ์ฃผ์๊ฐ์ ๋ณต์ฌํด ๋ฃ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ nested list์ ์ฃผ์๊ฐ์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ข ์๋ ๊ด๊ณ๊ฐ ๋์ด์ ์ด๋ฐ ์ผ์ด ์ผ์ด๋ฌ๋ค. ์ด๊ฒ์ ํด๊ฒฐํ๊ธฐ ์ํ ๋ชจ๋์ด ์๋ค.
[:] ๋ copy()์ ๊ฐ์ ๊ธฐ๋ฅ์ด๋ค.
ํด๋น ๊ฐ์ฒด์ ํ์ ๊ฐ์ฒด๋ค์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋ก ํ ๋นํด์ ์์ ํ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ค.
In[1] : import copy
In[2] : a = ['Head', ['Sub']]
In[3] : b = copy.deepcopy(a)
In[4] : b[1].append('Sub2')
In[5] : print(a, b)
Out[1] : ['Head', ['Sub']] ['Head', ['Sub', 'Sub2']]
์ ํด๊ฒฐ๋์์์ ๋ณผ ์ ์๋ค.
del ํค์๋๋ก ๋ณ์๋ฅผ ๋ช ์์ ์ผ๋ก ์ ๊ฑฐํจ์ผ๋ก์ ๋ณ์์ ์ ์ธ์ ์ทจ์ํ๊ณ ํ์์๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ์ ์ง์ธ ์ ์๋ค.
In[1] : a = 1000
In[2] : print(a)
Out[1] : 1000
In[3] : del a
In[4] : print(a)
NameError : name 'a' is not defined
ํน์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ์ฐธ์กฐํ๋ ๊ณณ์ ์์ด๋ค. 0์ด ๋ ๊ฒฝ์ฐ ๋ค์ GC๋ ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ๋๋ค.
import sys
In[1] : a = {'Jewelry', 'Kim'}
In[2] : b = a
In[3] : print(sys.getrefcount(a))
Out[1] : 3 # 3 ์ธ๊ฒ์ ์ฃผ์
์ฌ๊ธฐ์ 3์ด ๋์จ ์ด์ ๋ 1 . a๋ฅผ ์ ์ธํ ๋ + 1 2 . b ๋ฅผ a์ ์ฐธ์กฐ๋ก ์ฐ๋ฉด์ +1 3 . sys.getrefcount์์ ์ธ์๋ก ์ฐ๋ฉด์ +1 ์ด๋ ๊ฒ 3์ด ๋ ๊ฒ์ด๋ค.
ํ์์๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋์ผ๋ก ํด์ ํ๋ค. ์ด๋ reference count๋ฅผ ์ด์ฉํ๋ค. ๋ํ Generation์ ๋๋ ์ ๊ด๋ฆฌํ๋ค. (0,1,2 ์ธ๋), ์ธ๋๋ง๋ค ๊ฐ์ง๊ณ ์์ ์ ์๋ ๋ฉ๋ชจ๋ฆฌ์ ๊ฐ์ threshold๊ฐ ์กด์ฌํ๋ค. 0์ด ๊ฐ์ฅ youngํ ์ธ๋๊ณ 2๋ก ๊ฐ์๋ก oldํ ์ธ๋๊ฐ ๋๋๋ฐ ๊ฐ์ฅ youngํ ์ธ๋๋ถํฐ GC๋ฅผ ํ๋ค. ๊ทธ ์ด์ ๋ ๊ฐ์ฅ ์ต๊ทผ์ ์ ์ธ๋ ๋ณ์์ผ์๋ก ์ธ๋ชจ์์ด์ง ๊ฐ๋ฅ์ฑ์ด ๋๊ธฐ๋๋ฌธ์ด๋ค.(ex. loop๋ฅผ ๋๋ ์ ์ธํ ์ธ๋ฑ์ค ๋ณ์)
๊ฐ ์ ๋ค๋ ์ด์ ๋ง๋ค 3๊ฐ์ฉ ๋ค์ด๊ฐ ์ ์๋ค.
malloc ํจ์๊ฐ ์ํ๋๊ณ a๊ฐ ์๋ 'alpha'๊ฐ 0์ธ๋์ ๋ค์ด๊ฐ๋ค.
collect ํจ์๊ฐ ์ํ๋๊ณ 0 ์ ๋ค๋ ์ด์ ์์ refcount๊ฐ 0์ผ ๊ฒฝ์ฐ ์ง์ฐ๊ณ ์๋ ๊ฒฝ์ฐ 1 ์ ๋ค๋ ์ด์ ์ผ๋ก ์ฌ๋ฆฐ๋ค.
collect๊ฐ ํ๋ฒ ๋ ์ํ์ด ๋๊ณ refcount๊ฐ 0์ธ bravo๋ ์์ ์ญ์ ๊ฐ ๋์๋ค. ๊ทธ๋ฆฌ๊ณ 2์ธ๋๊น์ง ์ฌ๋ผ๊ฐ๊ฒ ๋์๋ค.
In[1] : import gc
In[2] : print(gc.get_threshold())
Out[1] : (700, 10, 10) # 0, 1, 2 generaion์ threshold๊ฐ ํํํํ๋ก ์ถ๋ ฅ
output์ (700, 10, 10) ์ ๋ป์ ์์๋ณด์ 1 . 700 ํ ๋นํ ๋ฉ๋ชจ๋ฆฌ์ ์๊ฐ ํด์ ํ ์๋ณด๋ค 700์ด ๋ ๋ง์ ๋ == ํ ๋นํ ๋ฉ๋ชจ๋ฆฌ - ํด์ ํ ๋ฉ๋ชจ๋ฆฌ ์ ์ด๋ gc๊ฐ ์๋์ผ๋ก ์คํ๋๋ค. (์๋์ผ๋ก๋ ์คํ์ํฌ ์ ์์.) 2 . ์ฒซ๋ฒ์งธ 10 0์ ๋ค๋ ์ด์ ์ gc ์คํํ์๊ฐ 10์ด ๋๋ฉด 1์ ๋ค๋ ์ด์ ์์๋ gc๋ฅผ ์คํํ๋ค. 3 . ๋๋ฒ์งธ 10 1์ ๋ค๋ ์ด์ ์์ gc ์คํํ์์ 10์ด ๋๋ฉด 2์ ๋ค๋ ์ด์ ์์๋ gc๋ฅผ ์คํํ๋ค.
์ด๋ฐ ์์ผ๋ก ์ธ๋์ฐจ์ด๋ฅผ ๋์๋ค๋ ๊ฒ์ ์ ์ ์๋ค. threshold๋ฅผ ๋ฐ๊ฟ ์๋ ์๋ค.
threshold ๋ฐ๊พธ๊ธฐ
In[1] : import gc
In[2] : gc.set_threshold(800, 20, 20)
๋ง๊ทธ๋๋ก ์ฝํ ์ฐธ์กฐ๋ฅผ ํ ์ ์๋ ๋ชจ๋์ด๋ค. refcount๊ฐ ์ฆ๊ฐํ์ง ์์ผ๋ฉด์ ํน์ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐ๊ฐ๋ฅํ๋ค. ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ง์ด ์ฐ์ง๋ง ํ์์ ์ด์ง๋ ์์ ์ด๋ฏธ์ง ์บ์ฑ๊ฐ์ ๊ฒฝ์ฐ์ ์ฌ์ฉํ๋ค.(๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณ์ ์ก์๋จน์ง ์๋๋ค.)
- weakref.ref(obj, callback = None) ์ด๋ฐ ์์ผ๋ก ์ฌ์ฉํ๋ค. ํด๋น ๊ฐ์ฒด์ weakref๋ฅผ ์์ฑํ๊ณ ๋ฐํํ๋ค. ํด๋น weakref๋ฅผ ํธ์ถํจ์ผ๋ก์ ์๋ณธ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ค๊ณ ์ฐธ์กฐํ๋ ๊ฐ์ฒด๊ฐ ์์ ์์ ์๋ฌ๊ฐ ์๋ None์ ๋ฐํํ๋ค.(gc๋ ๋)
import weakref
class SomeClass(object):
def __init__(self, *args):
super(SomeClass, self).__init__(*args)
a = SomeClass()
b = weakref.ref(a)
print(b())
Out : <__main__.SomeClass object at 0x7fae6c2c04c0>
del a
print(b())
Out : None
cache = None
def get_image():
if cache is None:
image = Image(file('image.png', 'rb').read())
cache = weakref.ref(image)
return cache
show(get_image())
...
# other codes
...
show(get_image())
๋์ ์
s = ''
for x in somelist:
s += some_function(x)
์ข์ ์
''.join(map(some_fuction, somelist))
๋์ ์
s = 'Hello!' + first_name + ' ' + last_name + '!'
์ข์ ์
s = 'Hello! {} {}'.format(first_name, last_name)
์ด์ ๋ + ๋ก concat์ ํ ๋ ๋ฉ๋ชจ๋ฆฌ ์ฌํ ๋น์ ํ๋ ์ฑ๋ฅ์ด ์ ํ๊ฐ ๋๋ค. python์์ ์ ๊ณตํ๋ join, format ๋ฑ์ ํจ์๋ก ๊ทน๋ณตํ์.
iterate ๋์ค ๋ณ๊ฒฝ๋๋ ๊ฐ์ฒด์ ๊ฒฝ์ฐ ๋ณต์ฌํด์ ์ฌ์ฉํ์.
๋์ ์
for k, v in somedict.items():
somedict[k] = v * 2 # ๋์
๋๋ฆฌ์ value ๊ฐ์ ๋๋ฐฐ์ฉํด์ค๋ค.
์ข์ ์
for k, v in somedict.copy().items():
somedict[k] = v * 2
๋์ ์
f = file('test.pak', 'rb')
data = f.read()
print(data) # data๋ฅผ ์ฝ์ ๋ค์๋ ๊ณ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ์ ํ๊ณ ์๋๋ค.
์ข์ ์
with file('test.pak', 'rb') as f:
data = f.read()
print(data) # with scope ์์์๋ง ์ ์ ํ๋ค.
์ฐธ์กฐํ ์์ ์ ํ๋ธ ์์ '๋ฐฐ์คํ: ํ์ด์ฌ ๋ฉ๋ชจ๋ฆฌ ์ด๋ชจ์ ๋ชจ - PyCon Korea 2015 '์ ๋ง์ด ์ฐธ์กฐํ์ฌ ๊ธ์ ์์ฑํด๋ณด์์ต๋๋ค. ๋ฐ๋ ๋ด์ฉ์ด๋ ํ๋ฆฐ ๋ด์ฉ์ ๋๊ธ, ์ด๋ฉ์ผ๋ก ํผ๋๋ฐฑ ๋ถํ๋๋ฆฝ๋๋ค.
ํธ๋ฆฌํจ๋ง ๋ฐ๋ผ๋ณด๋ฉด 100์ ์ง๋ฆฌ ํ๋ก๊ทธ๋๋จธ๊ฐ ๋ ์ ์๋ค๊ณ ์๊ฐํ์ต๋๋ค. ํธ๋ฆฌํจ ์์๋ ๋ณด์ด์ง ์๊ฒ ์๋ํ๋ ๋ง์ ๋์๋ค์ด ์์ต๋๋ค. ๊ทธ ๋์๋ค์ ์๊ณ ์ฌ์ฉํ ๋ ์ง์ ์ผ๋ก ์ ์ฌ์ฉํ ์ค ์๋ ํ๋ก๊ทธ๋๋จธ๊ฐ ๋์ง ์์๊น ์๊ฐํฉ๋๋ค. ๋ ๊น์ ๊ณต๋ถ๋ฅผ ํด๋ด ์๋ค! ๐