Language/Python

Python - 지능형 리스트 (List Comprehension)/제너레이터 표현식 (Generator expression) 의 이해 및 비교

TechNote.kr 2019. 9. 13. 18:42
728x90

지능형 리스트 (List Comprehension) : 
 Python 에서는 리스트 구성을 위해 항목을 하나하나 나열하는 방식외에 구문을 통해 sequence 형태의 데이터를 가공하여 리스트를 구성하는 방법을 제공하고 있다. 지능형 리스트를 사용하게 되면 코드가 간결해지고 상황에 따라서는 성능이 좋은 코드를 작성할 수 있다.
 
제너레이터 표현식 (Generator expression) :
 지능형 리스트 (List Comprehension) 과 유사하지만 별도의 리스트는 생성하지 않고, iterator 를 생성하여 항목을 하나씩 처리할 수 있도록 한다. 지능형 리스트를 만든 후 하나씩 항목을 처리하여도 되지만 별도의 메모리 공간을 차지하지 않는다는 차이점이 있다.

 지능형 리스트의 경우 대괄호 [] 를 사용하는 반면, 제너레이터 표현식은 괄호 () 를 사용하고 나머지 구문은 동일하다. 변수로 저장해 놓고 리스트 형태로 써야 하는 경우는 지능형 리스트의 형태로 사용하면 되고, 메모리에 유지할 필요가 없을 경우 제너레이터 표현식의 형태로 사용하면 된다.

 


지능형 리스트의 예)

 

Case 1> 별다른 조건 없이 0~9의 값을 가지고 있는 리스트의 생성

 

[지능형 리스트 사용하지 않았을 경우]

>>> result = []
>>> for idx in range(10):
...     result.append(idx)
... 
>>> print(result)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

[지능형 리스트 사용하였을 경우]

>>> result = [idx for idx in range(10)]
>>> print(result)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

 

Case 2> 0~9 의 값 중 짝수만 가지고 있는 리스트의 생성

 

[지능형 리스트 사용하지 않았을 경우]

>>> result = []
>>> for idx in range(10):
...     if idx % 2 == 0:
...          result.append(idx)
... 
>>> print(result)
[0, 2, 4, 6, 8]

[지능형 리스트 사용하였을 경우]

>>> result = [idx for idx in range(10) if idx % 2 == 0]
>>> print(result)
[0, 2, 4, 6, 8]

 

Case 3> 0~2, 0~2 의 데카르트 곱의 결과를 가진 리스트의 생성

 

[지능형 리스트 사용하지 않았을 경우]

>>> result = []
>>> for i in range(3):
...     for j in range(3):
...          result.append(i * j)
... 
>>> print(result)
[0, 0, 0, 0, 1, 2, 0, 2, 4]

[지능형 리스트 사용하였을 경우]

>>> result = [i * j for i in range(3) for j in range(3)]
>>> print(result)
[0, 0, 0, 0, 1, 2, 0, 2, 4]

 

Case 4> 0~2 의 값 중 2일 경우를 찾아 곱한 값을 가지고 있는 리스트의 생성

[지능형 리스트 사용하지 않았을 경우]

>>> result = []
>>> for i in range(3):
...     if i == 2:
...          for j in range(3):
...               if j == 2:
...                    result.append(i * j)
... 
>>> print(result)
[4]

[지능형 리스트 사용하였을 경우]

>>> result = [i * j for i in range(3) if i == 2 for j in range(3) if j == 2]
>>> print(result)
[4]

제너레이터 표현식의 예)

 

Case 1> 별다른 조건 없이 0~9의 값을 표현하는 iterator를 가진 제너레이터 표현식의 생성

>>> genexp = (idx for idx in range(10))
>>> print(genexp)
<generator object <genexpr> at 0x7f6367764af0>
>>> for item in genexp:
...     print(item)
... 
0
1
2
3
4
5
6
7
8
9

지능형 리스트와 제너레이터 표현식의 메모리 사용의 비교

 

>>> listcomp = [idx for idx in range(10)]
>>> sys.getsizeof(listcomp)
192
>>> listcomp2 = [idx for idx in range(100)]
>>> sys.getsizeof(listcomp2)
912

지능형 리스트의 경우 리스트를 생성하는 range 가 증가하면 이에 따라 해당 값을 저장하는 메모리 또한 증가하는 것을 볼 수 있다. 

 

>>> genexp = (idx for idx in range(10))
>>> sys.getsizeof(genexp)
88
>>> genexp2 = (idx for idx in range(100))
>>> sys.getsizeof(genexp2)
88

반면 제너레이터 표현식의 경우 실제 data를 만드는 것이 아니고 표현식이기 때문에 메모리 사용에는 변화가 없는 것을 볼 수 있다. 

 

 

 

728x90