728x90
728x90
# Ref
- https://yomangstartup.tistory.com/105
- https://pro-jy.tistory.com/38
- https://wikidocs.net/91520
- https://cjh5414.github.io/about-python-and-how-python-works/
- http://irakla.egloos.com/v/7444165
- https://crackerjacks.tistory.com/14
# 컴파일러와 인터프리터
- 고급 프로그래밍 언어를 어셈블리어로 번역해주는 방식의 차이
- 컴파일러 (complier)
- 전체 파일을 스캔하여 한번에 번역 -> 한 번 실행 파일이 만들어지고 나면 빠름
- 기계어 번역 과정에서 더 많은 메모리 사용
- 전체 코드를 스캔 후 오류를 출력하기 때문에 실행 전에 오류를 알 수 없음
- C, C++, JAVA
- 인터프리터 (interpreter)
- 한번에 한 문장씩 번역 -> 실행 시간이 느림
- 메모리 효율이 좋음
- 실행 중 오류를 만나면 바로 프로그램 중지
- Python, Ruby, Javascript
# 파이썬 실행 방식
- 파이썬 코드를 bytecode로 변환시키는 컴파일링 + 한 줄 한 줄 읽으며 해석하는 인터프리팅 혼합 사용
- 컴파일타임 : 파이썬이 실행되어 0과 1로 구성된 바이트코드로 변환되는 시간
- 런타임 : 변환된 코드를 메모리에 올려 차례차례 실행
- 런타임 시 bytecode는 python virtual macine이란 가상머신에서 실행 (외부 모듈은 이 때 추가됨)
- 파이썬 인터프리터의 종류 : cpython (default), pypy, jython ,,
# 파이썬 메모리 관리
- 메모리 할당 방식
- 정적 메모리 할당
- 프로그램 컴파일 시 메모리가 할당됨
- stack 자료구조로 구현
- 프로그램이 끝날때까지 없어지지 않음 : 메모리 재사용 불가
- 동적 메모리 할당
- 프로그램 런타임 시 메모리가 할당됨
- heap 자료구조로 구현
- 메모리에서 데이터 제거 가능 : 필요하지 않은 메모리 비우고 재사용 가능
- 정적 메모리 할당
- 변수 할당
- 파이썬은 정적변수/동적변수를 구분하지 않으며,
(인터프리터마다 다르지만) cpython의 경우 전부 heap에 올림 - 파이썬의 모든 변수는 객체로 간주된다 : 모든 변수는 어떤 메모리 공간으로의 레퍼런스를 가짐
- cpython에서의 immutable(아래에서 설명)한 변수들에 대한 메모리 관리 예제 (출처)
- 파이썬은 정적변수/동적변수를 구분하지 않으며,
# mutable, immutable
- 위의 예제는 immutable (변경 불가능)한 객체인 int형 객체였다
- 따라서 메모리 상에서 object는 변하지 않고, reference만 변경되었다 (interning)
- immutable : int, float, bool, str ,,,
- mutable : list, dict
- a, b, c에 각각 int인 1을 넣어줬을 땐, 1이라는 동일한 객체를 바라보고 있으므로 id값들이 모두 같다
- a, b, c에 각각 list인 [1,2,3] 을 넣어준 경우, mutable한 list type의 변수이므로 각각 다른 id값을 갖는다
- 따라서 안의 내용이 달라져도 레퍼런스값이 달라지지 않는다
- 이는 다시말해 레퍼런스값만 알면 오브젝트값을 변화시킬 수 있다는 뜻이 되는데,
- 단순히 list를 복사하는 경우, 주소값을 복사하기 때문에 (shallow copy) 원본 객체의 데이터를 수정할 수 있게 된다
# 얕은 복사 (shallow copy), 깊은 복사 (deep copy)
- 얕은 복사 : 원본 객체의 주소값을 복사함
- 깊은 복사 : 원본 객체가 참조하는 객체 자체를 복사
- 깊은 복사를 하기 위한 방법 (출처)
copy 모듈의 deepcopy() 이용 : 가장 많이 쓰임
import copy
a = [1, 2, 3]
b = copy.deepcopy(a)
각 클래스의 copy() 함수 이용
a = [1, 2, 3]
b = a.copy()
그 외,,,
a = [1, 2, 3]
# list 생성 시 매개변수에 원본 전달
b = list(a)
# list 생성 후 원본 리스트로 확장
c = []
c.extend(a)
# list slicing
d = a[:]
# 배열 요소로의 접근을 통한 복사
e = [i for i in a]
f = []
for i in a:
f.append(i)
이런저런 여러 방법들이 있으나, 처리 속도 면에서는 list slicing이 제일 빠르고, deepcopy가 제일 느리다고 한다
from copy import deepcopy
dignore = {str: None, int: None, type(None): None}
if __name__ == '__main__':
import copy
from time import time
num_times = 100000
L = [None, 'blah', 1, 543.4532,
['foo'], ('bar',), {'blah': 'blah'},]
t = time()
for i in range(num_times):
copy.copy(L)
print('copy.copy: ', time()-t)
t = time()
for i in range(num_times):
copy.deepcopy(L)
print('copy.deepcopy: ', time()-t)
t = time()
for i in range(num_times):
L.copy()
print('L.copy(): ', time()-t)
t = time()
for i in range(num_times):
list(L)
print('list(L): ', time()-t)
t = time()
for i in range(num_times):
a = []
a.extend(L)
print('a.extend(L): ', time()-t)
t = time()
for i in range(num_times):
L[:]
print('L[:]: ', time()-t)
t = time()
for i in range(num_times):
[i for i in L]
print('[i for i in L]: ', time()-t)
t = time()
for i in range(num_times):
a = []
for y in L:
a.append(y)
print('for y in L: a.append(y):', time()-t)
각 deep copy별 시간 계산하는 것을 좀 더 내가 보기 쉽게 고쳐보았다
그렇다고 한다
끝
728x90
728x90
'공부 > Python' 카테고리의 다른 글
[Django] admin에 keycloak login 붙이기 (1) | 2024.03.30 |
---|---|
[boto3/paginator] EC2 Name Tag를 포함한 엑셀 뽑기 (0) | 2022.05.13 |
[Python] Python to Slack 2 : Slack Bot Message 보내기 + 쉽게 Formatting하기 (Block Kit Builder) (0) | 2022.01.22 |
[Python] Python to Slack 1 : Slack Bot 만들고 설정하기 (0) | 2022.01.22 |
[Python] CSV 파일 읽기/쓰기 (0) | 2021.04.30 |
댓글