파이썬 정리
- -
파이썬
파이썬은 1991년 Guido van Rossum이 개발한 인터프리터 언어다. 프로그래밍 교육을 위해 많이 사용되고 기업의 실무에서도 많이 사용하는 언어다. 대표적으로 구글의 소프트웨어 절반 이상이 파이썬으로 작성되었다고 한다. 왜 파이썬을 많이 사용할까?
🔺 오픈소스 = 무료!
🔺 문법이 간단해 쉽게 배울 수 있다.
- Easy-to-learn
- Easy-to-read
- Easy-tomaintain
🔺 풍부한 라이브러리로 개발 생상성이 높다.
파이썬은 numpy, pandas, matplotlib 등 데이터 적재, 시각화, 통계 등에 필요한 라이브러리를 가지고 있다. 또한 범용 프로그래밍 언어로서 그래픽 사용자 인터페이스(GUI)나 Django, Flask 등을 이용한 웹서비스를 만들 수 있다.
🔺 다양한 플랫폼과의 호환 가능
파이썬은 Cross-Platfrom Language 로 윈도우에서 작성한 파이썬 프로그램을 그대로 리눅스 시스템에서도 실행이 가능하다. (Mac, Windows, Linux, Raspberry Pi 등과 호환 가능)
🔺 C언어와 찰떡궁합
전반적인 뼈대는 파이썬으로 만들고 빠른 실행 속도가 필요한 부분은 C로 만들어 파이썬 프로그램 안에 포함시킨다.
✅ 파이썬 언어의 특징
1) 고급 언어 (high-level)
2) 인터프리터 언어
파이썬은 부분 컴파일 언어이자 인터프리터 언어다. 컴파일 언어처럼 하드웨어를 직접 제어하는 작업은 불가능하다.
👆 인터프리터 언어란?
리스프, 자바스크립트, 파이썬, SQL, 루비, ...
명령어를 한 줄씩 읽어 바로 처리하는 언어로 중간 컴파일 단계 없이 번역과 실행이 동시에 이루어진다. 한 줄씩 명령어를 처리하므로 빠르게 실행할 수 있지만 명령 자체의 속도는 컴파일러 언어에 비해 느리다. 그리고 실제 실행하기 전까지 코드의 문제를 잡아낼 수 없어 오류를 제 때 잡아내기 어렵다.
👆 컴파일 언어란?
C, C++, Go, ...
전체 명령어를 한 번에 컴파일 한 뒤 다른 목적 코드로 번역한 후 한 번에 실행하는 언어다. CPU가 알아들을 수 있는 low-level 언어 (어셈블리 언어, object code, 기계어)로 번역된 후, 실행 가능한 파일이 생성된다. 즉, 번역과 실행이 따로 이루어진다. 규모가 큰 소스의 경우 프로그램 실행 전 기계어로 컴파일하는 데 시간이 오래 걸릴 수 있다.
3) 순수 객체 지향언어
C++
파이썬은 순수 객체 지향언어로 모든 것이 객체로 취급된다.
객체 지향 언어는 실세계를 모델링해 개발하는 프로그래밍 언어다. 각 개발 기능을 모듈화 함으로써 중복 연산하지 않고 재활용해 처리량을 줄인다. 캡슐화, 상속, 다형성이라는 세 가지 특징을 갖는다.
👆절차 지향 언어란?
C
순차적인 처리가 중요시 되어 프로그램 전체가 유기적으로 연결되도록 만드는 프로그래밍 언어다. 컴퓨터 처리 방식과 유사해 객체지향 언어에 비해 처리 시간이 빠르다.
4) 높은 가독성
파이썬은 기본적으로 '가장 아름다운 하나의 답이 존재한다'는 디자인 철학을 갖고 있다. 명확한 권장 코드 스타일 가이드가 있으며 다른 언어에는 없는 Pythonic 이라는 개념이 있다.
👆 권장 코드 스타일 가이드 PEP 8
- Python Enhancement Proposal
- 작명 규칙 (상수는 대문자+밑줄, 변수는 소문자+밑줄 등)
- 문법 규칙 (import / 할당 연산자(=) 앞뒤로 공백 넣기 등)
- 코드 스타일을 자동으로 권장사항에 맞춰주는 패키지도 있다.
5) 다양한 편의 기능 제공
- Dynamically typed : 동적 언어라 데이터 유형으로 변수를 선언할 필요가 없다.
반복 가능한 객체(iterable)
: 집합, 문자열, 리스트, 튜플, 딕셔너리, 함수까지도 반복문에서 사용할 수 있다. 제너레이터의 경우, 미리 만들어놓는 게 아니라 호출 될 때 반환값을 새로 만들어 반환하는 방식이기 때문에 메모리 관리 면에서도 이점이 있다.- 데코레이터 : 함수 구조를 변경하지 않고 기존 함수에 기능을 추가하는 함수
✅ 파이썬이 느린 이유
- 인터프리터 실행으로 빠른 개발이 가능하지만 동적 유형 검사 등 많은 실행 오버헤드가 발생해 느리다.
- 포트란이 파이썬에 비해 100배 빠르다!
- 동적 타이핑으로 인해 인터프리터가 변수의 유형을 알지 못하기 때문에 타입 정보를 먼저 찾은 뒤 연산을 진행해야 한다. 이것이 숫자 데이터에 관한 연산에서 C언어와 비교했을 때 파이썬이 느린 가장 큰 이유가 된다.
- 비효율적인 메모리 액세스가 발생할 수 있다.
- 파이썬의 리스트는 배열과 달리 포인터로 데이터에 접근하기 때문에 접근할 때 더 많은 액세스가 발생한다.
✅ 메모리 구조와 관리 방법
파이썬은 python memory manager가 자동으로 메모리를 관리해준다. 사람이 직접 메모리를 관리하지 않아도 되어 편리하지만 그만큼 최적화는 덜 되어 있다. 특히 비동기 코드는 메모리 관리에 노력해야 한다. 성능이 좋아야하는 장기 프로그램의 경우 여전히 수동 메모리 관리 기능을 사용하기도 한다.
- python private heap space : 메모리 관리를 위해 숨겨진 힙 스페이스 사용
- 인터프리터가 포인터를 사용해 힙 메모리 영역을 조정하고 메모리가 필요할 때마다 OS와 소통하면서 할당한다.
- 인터프리터가 스페이스를 관리하므로 프로그래머는 이 공간에 접근이 불가능하다.
- 객체의 레퍼런스 카운팅 값이 0이 되거나 도달할 수 없는 경우가 될 때 메모리에서 해제한다.
- 빌트인 가비지 컬렉터(Garbage Collector; GC)를 통해 메모리 재활용하고 해제 가능하다.
👆Garbage Collector 란?
GC는 세대(generation)와 임계값(threshold)을 통해 가비지 컬렉션 주기와 객체를 관리한다.
세대는 0~2세대로 구분되고 최근 생성된 객체는 0세대(young)에 들어가고 오래된 객체일수록 2세대(old)로 이동한다. 각 세대마다 가비지 컬렉터 모듈에는 임계값 개수의 개체가 있고 객체 수가 해당 임계값을 초과하면 가비지 콜렉션이 콜렉션 프로세스를 trigger(추적)한다. 해당 프로세스에서 살아남은 객체는 이전 세대로 이동한다.
- GC를 수행하려면 응용 프로그램을 완전히 중지해야 한다.
- GC 주기가 짧다면 응용 프로그램이 중지되는 상황이 증가하고 반대로 주기가 길어진다면 메모리 공간에 garbage가 많이 쌓이게 된다.
--> GC를 수정하는 것보다 컴퓨터 자원을 증가시키는 편이 훨씬 좋다.
기타
파이썬 코드 실행 과정
- 소스코드
.py
로 작성된 소스 코드를 파이썬 컴파일러가 읽으며 문법 오류 검사를 진행
문법 오류 발견시 즉시 컴파일 과정을 멈추고 에러 메세지 출력
- 컴파일러
컴파일러가 소스 코드를 바이트 코드로 변환한다. 바이트 코드는 하드 디스크의 .pyc 파일에 저장 (pycache 폴더 안에 생성)- Lexing : 전달된 코드를 라인을 쪼개 Token으로 일반화
- Parsing : 토큰들이 parser에게 전달되어 데이터를 구조적으로 나타냄
- Compiling : AST가 컴파일러에게 전달되고, 컴파일러가 AST를 이용하여 ByteCode 라는
.pyc
형태의intermediate language code
를 생성
- PVM (Python Virtual Machine)
실제 interpreting 작업을 담당하며, byte code를 기계어로 변환하여 실행한다. PVM은 바이트 코드를 컴퓨터가 실행할 수 있는 기계어로 한 줄 한 줄 (line by line) 번역한다.
제일 먼저 바이트 코드 로 컴파일 되고, 바이트 코드는 인터프리터를 통해 실행된다.
파이썬의 구현체
- CPython : 파이썬을 C언어로 구현한 구현체
- 인터프리터이면서 컴파일러로 파이썬 코드를 컴파일해서 bytecode로 바꾸고 인터프리터가 실행된다.
- PyPy3 : python 자체로 구현한 구현체
- JIT(Just In Time) 컴파일을 겸비한 인터프리터
- 기계어 코드를 생성하면서 그 코드를 캐싱하여, 같은 함수가 여러 번 불릴 때 매번 기계어 코드를 생성하는 것을 방지한다. -> 빠르다!
- Jython
- 파이썬 코드를 java bytecode로 만들어서 JVM 에서 실행될 수 있도록 한다.
.py
파일을.class
파일로 컴파일
list 대신 NumPy 배열을 사용하는 이유
리스트는 삽입, 추가, 삭제 및 연결과 같은 효율적인 작업을 지원하는 효율적인 범용 컨테이너다. 하지만 요소별 덧셈 및 곱셈과 같은 "벡터화된" 연산을 지원하지 않고, 파이썬이 모든 요소에 대한 유형 정보를 저장해야 하고 유형 디스패치 코드를 실행해야 한다. 반면 Numpy는 벡터 및 행렬 연산 기능을 제공해 더 효율적으로 작업할 수 있다.
- NumPy 배열은 훨씬 적은 메모리를 사용하므로 코드를 보다 효율적으로 만든다.
- NumPy 배열은 더 빠르게 실행되며 런타임에 과도한 처리를 추가하지 않는다.
- NumPy는 읽기 쉬운 구문을 가지고 있어 프로그래머가 쉽고 편리하게 사용 가능하다.
파이썬의 멀티 스레딩 (GIL)
- 멀티 스레딩 패키지가 있지만 코드 실행 시간이 늘어난다.
- GIL(Global Interpreter Lock)이라는 제너레이터가 존재하기 때문이다.
- GIL은 한 번에 하나의 '스레드'만 실행할 수 있도록 한다.
- 스레드가 GIL을 획득하고 약간의 작업을 수행한 다음 GIL을 다음 스레드로 전달하는지 확인한다.
- 이것은 매우 빠른 시간에 발생하므로 인간의 눈에는 스레드가 병렬로 실행되는 것처럼 보이지만 실제로는 동일한 CPU 코어를 사용하여 번갈아 가며 하나씩 실행된다.
References
'CS > 자료구조 + 알고리즘' 카테고리의 다른 글
알고리즘 면접 대비 질문 리스트업 (3) | 2023.06.03 |
---|---|
자료구조 면접 대비 질문 리스트업 (0) | 2023.06.03 |
기타 알고리즘 (이진탐색/ 최대공약수와 최소공배수/ 소수 찾기/ 재귀와 반복/ DP와 분할정복/ 그리디/ 백트래킹/ 허프만 코딩) (1) | 2023.06.02 |
정렬 알고리즘 (0) | 2023.06.02 |
해시 테이블 (0) | 2023.06.01 |
소중한 공감 감사합니다