티스토리 뷰
파이썬을 공부하러 인터넷을 돌아다니다 흥미로운 걸 보게 되었다.
지능형 리스트(list comprehension)를 쓰느냐, map 함수를 쓰느냐에서 지능형 리스트를 쓰는 게 좋다는 것.
사실 지능형 리스트는 for 문이 들어가 있어서 map 함수를 쓰는 게 좋다고 생각했는데, 아니었다.
a = [sum(i) for i in s if i>20]
b = list(filter(lambda x x>20, map(sum,s))
만약에 리스트 내에 for 문이 들어 있는 값을 할당한다면, 무조건 리스트 컴프리 헨션이 빠르다.
이는 데이터 값이 많을수록 차이가 훨씬 난다.
https://testspoon.tistory.com/186
RePythonOOP 9일차 파이썬 컨테이너 VS 플랫, 가변 VS 불변, 리스트 컴프리 핸션
Insight 1. 리스트내에 for문을 통한 값 할당시 무조건 (지능형) 리스트 컴프리 핸션이 빠르다. 2. 가변 불변, 컨테이너, 플랫은 자주 보면서 외우려고 마음을 먹었다. (중요하고 나중에 다시 찾아 볼
testspoon.tistory.com
해당 글을 보면, 직접 어셈블리어를 비교해놓은 글도 볼 수 있다.
for문은 함수 자체가 실행 시 전체 프로세스가 반복이라 느리다.
반면에 리스트 컴프리헨션은 먼저 사용할 변수를 적재하고, 함수를 실행한다.
이 과정은 map도 마찬가지긴 하지만, 적재할 함수와 변수가 리스트 컴프리헨션보다 많아서 메모리 누적을 유발한다.
from dis import dis
# 빈리스트에 for문에서 append()사용 시
print(dis('''
list_ = []
for i in range(10):
list_.append(i)
'''))
# ----------------동기적 진행?--------------------
# 2 0 BUILD_LIST 0
# 2 STORE_NAME 0 (list_)
# 3 4 SETUP_LOOP 26 (to 32)
# 6 LOAD_NAME 1 (range)
# 8 LOAD_CONST 0 (10)
# 10 CALL_FUNCTION 1
# 12 GET_ITER
# >> 14 FOR_ITER 14 (to 30)
# 16 STORE_NAME 2 (i)
# 4 18 LOAD_NAME 0 (list_)
# 20 LOAD_METHOD 3 (append)
# 22 LOAD_NAME 2 (i)
# 24 CALL_METHOD 1
# 26 POP_TOP
# 28 JUMP_ABSOLUTE 14
# >> 30 POP_BLOCK
# >> 32 LOAD_CONST 1 (None)
# 34 RETURN_VALUE
# None
# 리스트 컴프리핸션
print(dis('[i for i in range(10) if i%2 == 0]'))
# -------------- 변수 적재,함수 호출과정-----------------
# 1 0 LOAD_CONST 0 (<code object <listcomp> at 0x7f146c1015d0, file "<dis>", line 1>)
# 2 LOAD_CONST 1 ('<listcomp>')
# 4 MAKE_FUNCTION 0
# 6 LOAD_NAME 0 (range)
# 8 LOAD_CONST 2 (10)
# 10 CALL_FUNCTION 1
# 12 GET_ITER
# 14 CALL_FUNCTION 1
# 16 RETURN_VALUE
# ----------- 함수 실행과정-----------------------
# Disassembly of <code object <listcomp> at 0x7f146c1015d0, file "<dis>", line 1>:
# 1 0 BUILD_LIST 0
# 2 LOAD_FAST 0 (.0)
# >> 4 FOR_ITER 20 (to 26)
# 6 STORE_FAST 1 (i)
# 8 LOAD_FAST 1 (i)
# 10 LOAD_CONST 0 (2)
# 12 BINARY_MODULO
# 14 LOAD_CONST 1 (0)
# 16 COMPARE_OP 2 (==)
# 18 POP_JUMP_IF_FALSE 4
# 20 LOAD_FAST 1 (i)
# 22 LIST_APPEND 2
# 24 JUMP_ABSOLUTE 4
# >> 26 RETURN_VALUE
# None
print(dis('list(filter(lambda i : i%2 == 0 , map(int, range(10))))'))
# -------------- 변수 적재,함수 호출과정-----------------
# 1 0 LOAD_NAME 0 (list)
# 2 LOAD_NAME 1 (filter)
# 4 LOAD_CONST 0 (<code object <lambda> at 0x7f146c1015d0, file "<dis>", line 1>)
# 6 LOAD_CONST 1 ('<lambda>')
# 8 MAKE_FUNCTION 0
# 10 LOAD_NAME 2 (map)
# 12 LOAD_NAME 3 (int)
# 14 LOAD_NAME 4 (range)
# 16 LOAD_CONST 2 (10)
# 18 CALL_FUNCTION 1
# 20 CALL_FUNCTION 2
# 22 CALL_FUNCTION 2
# 24 CALL_FUNCTION 1
# 26 RETURN_VALUE
# ----------- 함수 실행과정-----------------------
# Disassembly of <code object <lambda> at 0x7f146c1015d0, file "<dis>", line 1>:
# 1 0 LOAD_FAST 0 (i)
# 2 LOAD_CONST 1 (2)
# 4 BINARY_MODULO
# 6 LOAD_CONST 2 (0)
# 8 COMPARE_OP 2 (==)
# 10 RETURN_VALUE
따라서 map 함수니 for을 굳이 사용해야 하는 상황이 아니라면, 파이썬에서는 리스트 컴프리헨션 사용을 습관 들이는 게 좋을 듯 싶다.