[파이썬 코딩의 기술] 32. 긴 리스트 컴프리헨션보다는 제너레이터 식을 사용하라.

Dreamer ·2021년 7월 5일
0

1. 리스트 컴프리헨션(List Comprehension)

  • 리스트 등 순회형 컨테이너 객체로부터 이를 가공한 새로운 리스트를 생성하는 방법
  • Set, Dict에 대해서도 적용 가능함.
my_list = ['a','b','c','d']
result_list = [(i,j) for i in range(2) for j in my_list]
print(result_list) 

2. 리스트 컴프리헨션의 문제점

  • 리스트 컴프리헨션의 가장 큰 문제점은 메모리 낭비.
  • 새 리스트를 통째로 생성하기 때문에 입력이 많은 프로그램에서는 Out of memory 에러 생성.
  • list의 경우 사이즈가 커질 수록 메모리 사용량이 증가, generator의 경우 사이즈가 커져도 차지하는 메모리 사이즈는 동일.
  • list의 경우 모든 데이터를 메모리에 적재하여 차지하는 메모리 용량이 커지지만, generator의 경우에는 데이터 값을 호출할 때마다 차례로 값에 접근하여 메모리에 적재하기 때문.
  • sys.getsizeof(): 객체의 메모리 사이즈 바이트 단위로 반환.

3. 리스트 컴프리헨션 vs 제너레이터

  • list comprehinsion
before = [1,2,3,4,5]
after = [v*2 for v in before if v % 2 ==0] 
  • Generator
before = [1,2,3,4,5]
after_gene = (v*2 for v in before if v % 2 == 0) 
print(after_gene)

  • 내장 함수(next)를 통해 출력 가능
  • 값을 호출하기 전까진 메모리에 올려져 있지 않음.
  • generator expression 제공되어 ()를 사용하면 됨.
  • 진행 순서는 일반 함수와 동일한 절차로 실행된다.
  • yield 만나게 되면 함수를 호출했던 구문인 첫 번째 값을 반환하게 됨.
  • 단, generator 함수는 유지된 상태, 그 후 for 문에 의해 다시 generator 함수가 호출됨.
  • generator 함수가 처음부터 시작되는게 아니라 yield 이후 구문부터 시작하게 된다.
  • i+=1-> 1이 산출됨.
  • x값은 1을 전달 받고 print 된다.

4. 제너레이터 합성

  • roots를 실행시킬 때, it도 함께 연쇄적으로 진행된다.
  • 메모리를 효율적으로 사용하면서 이뤄지게 됨.

요약
1. 입력이 크면 out of memory 문제 방지 차, 리스트 컴프리헨션 대신 제너레이터 사용
2. 제너레이터 식은 한 번에 원소 하나씩 출력하기 때문에 메모리 문제 피할 수 있음.
3. lazy evaluation, 즉 수행 시간이 긴 계산 결과 값이 필요할 때까지 계산을 늦추는 효과를 볼 수 있다.
4. 서로 연결된 제너레이터 식은 매우 빠르게 실행, 메모리 효율적 사용함.

  • 모든 iterator는 iterable 하지만, 모든 iterable가 iterator는 아니다.
  • 제너레이터는 이터레이터를 생성해주는 함수.
  • 이터레이터는 클래스에 iter, next또는 getitem 메서드를 구현해야 하지만 제너레이터는 함수 안에서 yield 라는 키워드만 사용하면 끝.
  • 제너레이터는 이터레이터보다 훨씬 간단하게 작성 가능.
  • 이터레이터는 raise로 StopIteration 에외
profile
To be a changer who can overturn world

0개의 댓글