
๋จ์ ๋ฌธ๋ฒ ์๊ธฐ๋ณด๋ค๋ ์ ๋ต์ ์ฌ๊ณ ์ ์ ์ฒด ๊ตฌ์กฐ ์ดํด๊ฐ ์ค์ํด์ง.
๋ฉ๋ชจ๋ฆฌ๋ ํจ์จ์ ์ธ ๊ด๋ฆฌ๋ฅผ ์ํด ์์ญ์ด ๋๋์ด ์์ต๋๋ค. ์ปดํจํฐ์ ๋ฉ๋ชจ๋ฆฌ(RAM) ์์์ ํ์ด์ฌ ํ๋ก๊ทธ๋จ์ด ์คํ๋ ๋์ ๊ตฌ์กฐ์ ๋๋ค.
| ์ฃผ์ ์์น | ์์ญ ์ด๋ฆ | ์ค๋ช ๋ฐ ํ์ด์ฌ์์์ ์ญํ | ํน์ง |
|---|---|---|---|
| High Address (๋์ ์ฃผ์) | Stack (์คํ) | ํจ์ ํธ์ถ(Call Frame)๊ณผ ๋ณ์ ์ด๋ฆ(Name) ์ ์ฅ | โข ํจ์๊ฐ ํธ์ถ๋ ๋ ์์ฑ๋๊ณ ๋๋๋ฉด ์ญ์ ๋จ โข ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๊ฐ ์์์ ์๋๋ก(โ) ๋ด๋ ค๊ฐ๋ฉฐ ํ ๋น๋จ โข LIFO (Last In First Out) ๊ตฌ์กฐ |
| โ๏ธ | (Free Space) | ์คํ๊ณผ ํ ์ฌ์ด์ ๋น ๊ณต๊ฐ | ์คํ์ ์๋๋ก, ํ์ ์๋ก ์๋ผ๋๋ฉฐ ๊ณต๊ฐ์ ๊ณต์ ํจ |
| Middle | Heap (ํ) | ์ค์ ๊ฐ์ฒด(Object, Value) ์ ์ฅ | โข ํ์ด์ฌ์ ๋ชจ๋ ๊ฐ(int, list, function ๋ฑ)์ ์ฌ๊ธฐ์ ์ ์ฅ๋จ โข ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๊ฐ ์๋์์ ์๋ก(โ) ์ฌ๋ผ๊ฐ๋ฉฐ ํ ๋น๋จ โข ์ฌ์ฉ์๊ฐ ๋์ ์ผ๋ก ์์ฑ (Dynamic Allocation) |
| Low Address (๋ฎ์ ์ฃผ์) | Data (BSS/Init) | ์ ์ญ ๋ณ์(Global Variable) ์ค์ ์ ๋ณด | โข Initialized: ์ด๊ธฐํ๋ ๋ฐ์ดํฐ โข Uninitialized (BSS): ์ด๊ธฐํ๋์ง ์์ ๋ฐ์ดํฐ โข ํ๋ก๊ทธ๋จ ์์ ์ ํ ๋น๋จ |
| Lowest | Text (Code) | ์์ค ์ฝ๋ (๊ธฐ๊ณ์ด) | โข ์คํํ ํ๋ก๊ทธ๋จ์ ์ฝ๋๊ฐ ์ ์ฅ๋๋ ์์ญ โข ์ฝ๊ธฐ ์ ์ฉ (Read-Only) |
int a = 10;์ ์ ์ธํ๋ฉด Stack ์์ญ์ 10์ด๋ผ๋ ๊ฐ์ด ์ง์ ์ ์ฅ๋ฉ๋๋ค.a = 10์ ์ ์ธํ๋ฉด Stack์๋ a๋ผ๋ ์ด๋ฆ(๋ณ์)๋ง ์๊น๋๋ค.10์ Heap ์์ญ์ ๊ฐ์ฒด๋ก ์์ฑ๋ฉ๋๋ค.a๊ฐ Heap์ 10์ ๊ฐ๋ฆฌํค๋(Reference/Binding) ๊ตฌ์กฐ์
๋๋ค.์ ๋ฆฌํ์๋ฉด:
์์ฑํ์ ๋ ธํธ ๋ด์ฉ์ฒ๋ผ "๋ณ์(์ด๋ฆ)๋ Stack์ ์กํ๊ณ , ์ค์ง์ ์ธ ๊ฐ(๊ฐ์ฒด)์ Heap์ ํ ๋น" ๋๋ ๊ฒ์ด ํ์ด์ฌ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ๊ฐ์ฅ ํฐ ํน์ง์ ๋๋ค. ์ด ๋๋ฌธ์ ํ์ด์ฌ์ ๋จ์ ์ ์ ํ๋๋ฅผ ์ ์ฅํ๋๋ผ๋ C์ธ์ด๋ณด๋ค ๋ ๋ง์ ๋ฉ๋ชจ๋ฆฌ(Overhead)๋ฅผ ์ฌ์ฉํ๊ฒ ๋ฉ๋๋ค.
๋ฐ์ดํฐ ํ์ ์ ๋ฐ๋ผ ๋ณ๊ฒฝ ๊ฐ๋ฅ ์ฌ๋ถ๊ฐ ๋ค๋ฆ ๋๋ค.
int, float, str, tuplelist, dict, sett = ('This', 'tuple', ['is', 'immutable', '?'])
# Case 1: ํํ์ ์์ ์์ฒด๋ฅผ ๋ณ๊ฒฝ ์๋
# t[2] = ['a', 'new', 'list']
# -> โ TypeError ๋ฐ์ (ํํ์ ๋ถ๋ณ)
# Case 2: ํํ ๋ด๋ถ์ ๊ฐ๋ณ ๊ฐ์ฒด(List)์ ๋ด์ฉ ๋ณ๊ฒฝ ์๋
t[2][2] = '!'
# -> โญ ์ ์ ์คํ (๋ฆฌ์คํธ๋ ๊ฐ๋ณ)
ํต์ฌ: Tuple์ ๊ทธ ์์ ๊ตฌ์ฑ์์(์ฃผ์๊ฐ)๋ฅผ ๋ฐ๊ฟ ์ ์์ง๋ง, ๊ทธ ๊ตฌ์ฑ์์๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฐ์ฒด(List)๊ฐ ๊ฐ๋ณ์ ์ด๋ผ๋ฉด ๊ทธ ๋ด๋ถ ๋ฐ์ดํฐ๋ ์์ ํ ์ ์๋ค.
Int, Str, Tuple ๋ฑ ๋ค์ํ ํ์
์ด ํผ์ฌ ๊ฐ๋ฅ.List -> Pointer -> PyObject Head(Type ์ฒดํฌ, Ref Count) -> ์ค์ ๊ฐํจ์์ ๊ธฐ๋ณธ ์ธ์๊ฐ(Default Argument)์ ํจ์๊ฐ ์ ์๋ ๋ ๋จ ํ ๋ฒ๋ง ํ๊ฐ(Evaluation)๋๊ณ ์์ฑ๋ฉ๋๋ค. ๋ง์ฝ list์ ๊ฐ์ ๊ฐ๋ณ ๊ฐ์ฒด(Mutable Object)๋ฅผ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ฌ์ฉํ๋ฉด, ํจ์๋ฅผ ํธ์ถํ ๋๋ง๋ค ํด๋น ๊ฐ์ฒด๋ฅผ ๊ณต์ ํ๊ฒ ๋์ด ์๋์น ์์ ๊ฒฐ๊ณผ๊ฐ ๋ฐ์ํฉ๋๋ค.
def myf(i=list()): # ํจ์ ์ ์ ์ list()๊ฐ ํ ๋ฒ๋ง ์์ฑ๋จ
i.append('first')
return i
a = myf()
b = myf()
print(a) # ['first', 'first'] -> a์ b๊ฐ ๊ฐ์ ๋ฆฌ์คํธ๋ฅผ ๊ณต์ ํจ
print(b) # ['first', 'first']
print(id(a) == id(b)) # TrueNone์ ์ฌ์ฉํ์ฌ ํธ์ถ ์๋ง๋ค ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋๋ก ์ฒ๋ฆฌ.def myf(i=None):
if i is None:
i = list() # ํธ์ถ๋ ๋๋ง๋ค ์๋ก์ด ๋ฆฌ์คํธ ํ ๋น
i.append('first')
return i# time.sleep()์ด ์คํ๋์ด 3์ด๋ฅผ ๊ธฐ๋ค๋ฆฐ ํ, [0] ์ธ๋ฑ์ฑ์ ํ๊ณ ๋ฆฌ์คํธ๋ ๋ฒ๋ ค์ง
['no sleep', time.sleep(1), time.sleep(2)][0]debug_log)๋ผ๋ ์ธ์๋ก ๋๊ธฐ๋ ํจ์(expensive_func)๊ฐ ๋จผ์ ์คํ๋์ด ์ฑ๋ฅ ์ ํ๋ฅผ ์ผ์ผํฌ ์ ์์ต๋๋ค.if __debug__: ๊ตฌ๋ฌธ์ด๋ O (Optimize) ์ปค๋งจ๋ ๋ผ์ธ ์ต์
์ฌ์ฉ.๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋๊ณผ ์๋ ๊ฐ์ Trade-off๋ฅผ ๊ณ ๋ คํด์ผ ํฉ๋๋ค.
Generator Expression (Laziness):
sum(x*x for x in range(1_000))
sum์ ์ ๋ฌ.List Comprehension (Eagerness):
sum([x*x for x in range(1_000)])
sum์ ์ ๋ฌ.pop(0)์ ๋ฆฌ์คํธ์ ์ฒซ ๋ฒ์งธ ์์๋ฅผ ์ ๊ฑฐํ๊ณ ๋๋จธ์ง ๋ชจ๋ ์์๋ฅผ ์์ผ๋ก ๋น๊ฒจ์ผ(Shift) ํ๋ฏ๋ก O(N) ๋น์ฉ์ด ๋ฐ์ํฉ๋๋ค. (๋งค์ฐ ๋นํจ์จ์ )math.sqrt)์ ๊ณ์ ์ฐพ๋ ๊ฒ๋ณด๋ค, ์ง์ญ ๋ณ์๋ก ๋ฐ์ธ๋ฉ(from math import sqrt ํน์ sqrt = math.sqrt)ํด์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ ๊ทผ ์๋๊ฐ ๋ ๋น ๋ฆ
๋๋ค.__slots____dict__ ์์ฑ์ ๋ง์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ๋ํญ ์ ๊ฐ (๋๋์ ์ธ์คํด์ค ์์ฑ ์ ์ ์ฉ).__dict__๊ฐ ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํธํ ์ ๋ ์ ์์).type)TypedDict (Dict), dataclass (Class), NamedTuple (Tuple) ์ค ์ ์ ํ ๊ฒ์ ์ ํ.