새소식

인기 검색어

독서

러닝 파이썬 읽으며 들었던 생각들 chapter1에서 4까지

  • -

기본기에 충실해지게 되는 책! 객체 타입 문자열 등 기본기만 거의 1800 페이지 가량 다룬다...

 

이 글은 이 책의 내용을 요약하는 것이 아닌, 읽으면서 어떤 생각이 들었던 부분들에 대해 적은 글입니다.

 

Chapter 2. 파이썬이 프로그램을 실행하는 방법

 

"파이썬에서 컴파일러는 항상 런타임에 나타나며, 프로그램을 실행시키는 시스템의 일부다." -p. 41

 

파이썬도 컴파일을 한다. 그런데 미리 해두고 사용하는 것이 아니라, import 문을 읽는 시점에 해당 소스를 컴파일한다. 이때 컴파일해서 나온 파일이 .pyc인데, 파이썬 바이트코드 형태로 쓰여져 있다.

 

그렇다면 같은 파일을 import할 때마다 매번 컴파일할까? 그건 아니다. 컴파일하기 전에 버전을 체크해서 이 소스가 이미 컴파일된 것은 아닌지, 컴파일된 이후에 변경점은 있는지를 체크한다.

 

여기서 들었던 생각은 2가지가 있다.

 

1. 확실히 빌드에 대해 고민할 필요가 사라지니 개발이 편하긴 한데, import하는 구문이 많아지면 느려지진 않을까?

 

이 부분은 확실히 처음엔 그럴 수도 있다. 하지만 서버가 돌아가는 환경에서 어쨌든 import는 일어날 것이고, 한 번 import하게 되면 그 후로는 같은 파일을 가지고 있을테니까 큰 문제가 아니게 될 것이란 생각이 들었다.

 

2. main 스크립트는 다른 데서 import하지는 않을테니 최적화가 불가능할까?

 

이래서 if __name__ == main: 구문에서 실행기만 위치시키나 보다

 

이렇게 해서 만든 pyc 파일을 PVM(Python Virtual Machine)에서 한 줄 한 줄 읽는다. java와 상당히 비슷하다. 이쯤 되면 Java => 컴파일 언어, Python => 인터프리터 언어 라는 공식은 인식이 좀 바뀌어야 할 듯 하다.

 

특히, Pypy 같은 경우에는 JIT Compiler를 제공한다는 점에서 더 유사하다고 느꼈다. (참고로 보편적으로 사용하는 구현은 CPython이다. Java로 치면 Hotspot과 같은 포지션이 아닐까 싶다)

 

정리하자면, python은

 

main 실행 => import 구문 조우 => pyc 파일 버전 체크 => (필요시 컴파일) => 바이트코드 메모리에 load => PVM에서 읽기

 

순으로 진행되는 듯 하다.

 

"런타임 시에 다른 파이썬 프로그램을 생성하고 실행하는 것이 가능하며, 이 기능은 종종 매우 유용하게 사용된다." -p. 41

"파이썬 코드는 실행 중에 변경될 수 있다. 그러므로 사용자는 운영 중인 시스템의 파이썬 부분을 전체 시스템의 소스 코드 없이, 그리고 코드에 대한 컴파일 없이 변경할 수 있다." -p. 41

 

이 부분에서 몽키패치가 가능한 점이 여기서 기인한게 아닐까 하는 생각이 들었다.

 

현재 몽키패치에 대해서 겉핥기 정도만 알고 있기 때문에 공부하고 채울 계획이다

 

Chapter 4. 파이썬 객체 타입 소개

 

"파이썬의 리스트는 다른 언어의 배열(array)을 연상시키기도 하지만, 일반적으로 배열보다 더 강력한 기능을 제공한다. 그중 하나로, 리스트는 고정된 타입 제약이 없다." -p. 138

 

"리스트는 고정된 타입 제약이 없다" 나는 이 부분을 보고 숨이 좀 턱 막히는 기분이 들었다. 이 말이 의미하는 바는 다음과 같다.

 

new_list = [123, 'aa', Person("현수")]

 

이력 행위가 가능하다는 의미이다. 물론 선언할 때는 편하겠지만, 꺼내다 쓰는 입장에서는 대체 여기에 어떤 타입이 들어올지 감이 안 잡히기 때문에 애좀 먹을 것 같다는 생각이 들었다.

 

아니면 내가 호들갑 + 자바에 뇌가 절여진 걸지도... 물론 팀원들 끼리 리스트에는 같은 타입만 넣자고 계약을 걸 수 있겠지만, 그렇다면 고정된 타입 제약이 없다는 장점이 못지켜지겠다는 생각이 들었다.

 

아니면 list를 반환하는 함수에 주석으로 이 리스트에 담길 수 있는 타입들을 명시하면 그나마 사용하는 입장에서 분기 처리할 수 있겠다는 생각이 들었다.

 

"파이썬 3.X에서 range가 생성하는 값을 표시하기 위해 list로 감쌀 필요가 있다. (2.X는 실제 리스트를 한 번에 만든다)." -p. 142

 

3.X에선 갑자기 왜 list로 감싸도록 변경되었을까? GPT 선생님에게 여쭤보니, range 함수에 큰 값이 들어오게 되면 메모리 소비가 크기 때문에 필요해질 때까지 최대한 지연 평가하는 것이라고 한다.

 

따라서 range() 객체를 반환하고, list()로 감싸야 그때서야 리스트로 만들어 주는 듯 하다.

 

근데 한 편으로는 어쨌든 메모리에 적재되는 건 맞으니까 메모리는 똑같이 쓰는 것 아닌가...? 싶기도 한데 뭔가 gc라던가 그 사이에 여러 동작들을 고려한 것일 수도 있고... 정확히는 모르겠다. 그냥 최적화에 대한 여지를 남겨두었다. 정도로 이해했다.

 

"아마 여러분은 리스트 컴프레헨션이 내장 함수인 map 또는 filter와 유사한 것이라고 말할 수도 있을 것이다." -p. 142

 

map이나 filter도 range와 마찬가지로 지연평가 한다고 한다. 그러나 이 경우에는 iterator를 반환한다고 한다.

 

"for 루프와 관련된 기능들은 객체를 '왼쪽에서 오른쪽' 순서로 단계별로 진행하며, 단순히 시퀀스 연산이 아닌 반복(iterable) 연산에 해당한다"

 

 

 

 

'독서' 카테고리의 다른 글

대체 뭐가 문제야  (0) 2023.11.07
그리스인 조르바  (0) 2021.02.01
카네기 인간관계론  (0) 2020.08.29
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.