IT/언어

[python] python의 Comprehension

개발자 두더지 2020. 8. 26. 13:41
728x90

Comprehension이란 iterable한 오브젝트를 생성하기 위한 방법 중 하나로 파이썬에서 사용할 수 있는 기능 중 하나이다.

파이썬에는 크게 네 가지 종류의 Comprehension이 존재한다.

- List Comprehension (LC)

- Set Comprehension (SC)

- Dict Comprehension (DC)

- Generator Expression (GE)


1. List Comprehension(LC)

List Comprehension은 리스트를 쉽게 생성하기 위한 방법이다. python에서 보편적으로 사용되는 기능으로 다양한 응용이 가능하다. 

먼저 아래의 예는 List Comprehension을 사용하지 않은 경우이다.

L1 = []
for x in range(30):
  L1.append(x**2)
print(L1)

# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841]

 

1) List Comprehension의 기본형

List Comprehension을 사용한다면 append메서드를 사용하지 않고 단 한 줄의 코드로 같은 위와 동일한 리스트를 작성할 수 있다형. List Comprehension의 기본적인 형태는 다음과 같다.

[식 for 임의의 변수명 in iterable객체]

리스트나 튜플 등 iterable객체의 각 요소를 임의의 변수로 꺼내 식을 적용하여 그 결과가 요소가 되는 새로운 리스트가 리턴되는 방식이다. 따라서 위의 예시를 적용하여 동일한 결과를 아래와 같이 작성할 수 있다.

L2 = [x**2 for x in range(30)]
print(L2)

# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841]

 

2) if로 조건분기하는 List Comprehension

같은 줄에 조건(if)을 설정하여 원하는 숫자만으로 이루어진 list를 만들 수 있다.

L3 = [x**2 for x in range(30) if x % 2 == 0]
print(L3)

# [0, 4, 16, 36, 64, 100, 144, 196, 256, 324, 400, 484, 576, 676, 784]

 

3) 삼항 연산자의 활용 (if else등의 처리)

위의 예세서는 조건을 만족하는 요소만 새로운 리스트에 포함되어 반환되고 조건을 만족하지 못한 요소는 삭제된다. 그러나 if else와 같이 조건을 만족하지 않은 요소에 대해서도 별도의 처리가 필요한 경우 삼항 연산자를 이용하여 if esle와 같은 처리를 할 수 있다.

Python에서는 삼항 연사자를 아래와 같이 쓸 수 있다.

조건과 일치했을 때의 값 if 조건식 else 일치하지 않을때의 값

위의 삼항 연산자를 List Comprehension에 적용했을 때는 아래와 같이 된다.

[조건과 일치했을 때의 값 if 조건식 else 불일치시의 값 for 임의의 변수명 in iterable객체]
odd_even = ['odd' if i % 2 == 1 else 'even' for i in range(10)]
print(odd_even)
# ['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']

 

4) 중첩 for문의 활용

또한 중첩된 for문을 한 줄로 정의하는 것도 가능하다. for 루프를 중첩하여 복수의 iterable객체를 결합할 수 있다.

[식 for 변수명1 in iterable객체1
	for 변수명2 in iterable객체2
    	for 변수명3 in iterable객체3]
L4 = [(x, y) for x in range(10) for y in range(x, 10)]
print(L4)

# [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (2, 2), (2, 3), (2, 4), (2, 5), (2, 6), (2, 7), (2, 8), (2, 9), (3, 3), (3, 4), (3, 5), (3, 6), (3, 7), (3, 8), (3, 9), (4, 4), (4, 5), (4, 6), (4, 7), (4, 8), (4, 9), (5, 5), (5, 6), (5, 7), (5, 8), (5, 9), (6, 6), (6, 7), (6, 8), (6, 9), (7, 7), (7, 8), (7, 9), (8, 8), (8, 9), (9, 9)]

 

5) zip(), enumerate()와의 결합

for문에서 자주 사용되는 편리한 함수로 복수의 리터널을 모아주는 zip()이나 인덱스와 값을 return하는 enumerate()가 있다.

zip()이나 enumerate()를 List Comprehension에 사용하는 것도 물론 가능하다. 특수한 문법을 사용하는 것이 아니므로 for문과의 대응을 생각하면 그렇게 어렵지 않다.

아래는 zip()의 예이다.

l_str1 = ['a', 'b', 'c']
l_str2 = ['x', 'y', 'z']

l_zip = [(s1, s2) for s1, s2 in zip(l_str1, l_str2)]
print(l_zip)
# [('a', 'x'), ('b', 'y'), ('c', 'z')]

아래의 코드는 enumerate()를 활용한 예시이다.

l_enu = [(i, s) for i, s in enumerate(l_str1)]
print(l_enu)
# [(0, 'a'), (1, 'b'), (2, 'c')]

2. Set Comprehesion(SC)

List Comprehension에서 괄호를 {}로 변경하면 집합이 생성된다.

{식 for 임의의 변수명 in iterable객체}

간단한 예시는 아래와 같다.

s = {i**2 for i in range(5)}

print(s)
# {0, 1, 4, 9, 16}

3. Dict Comprehension (DC)

사전형 객체도 Comprehension으로 생성할 수 있다.

{}안에 식의 부분에 키와 값 2개를 '키: 값'과 같이 지정하여 작성하면 된다.

{키:값 for 임의의 변수명 in iterable객체}

키와 값에는 임의의 식을 지정할 수 있다.

l = ['Alice', 'Bob', 'Charlie']

d = {s: len(s) for s in l}
print(d)
# {'Alice': 5, 'Bob': 3, 'Charlie': 7}

키와 값 각각의 리스트로부터 새로운 사전을 만들고 싶은 경우는 zip()를 사용하면 된다.

keys = ['k1', 'k2', 'k3']
values = [1, 2, 3]

d = {k: v for k, v in zip(keys, values)}
print(d)
# {'k1': 1, 'k2': 2, 'k3': 3}

4. Generator Expression (GE)

List Comprehension의 각괄호'[]'를 둥근괄호'()'로 한 경우는 튜플이 아닌 제네레이터를 리턴한다. 그것을 Generator Expression이라고 한다.

List Comprehension의 표기 예

l = [i**2 for i in range(5)]

print(l)
# [0, 1, 4, 9, 16]

print(type(l))
# <class 'list'>

Generator 식의 예.

Generator은 그대로 print()문을 이용해도 내부의 값이 출력되지 않지만 for문을 돌리면 내부의 값을 확인할 수 있다. 

g = (i**2 for i in range(5))

print(g)
# <generator object <genexpr> at 0x10af944f8>

print(type(g))
# <class 'generator'>

for i in g:
    print(i)
# 0
# 1
# 4
# 9
# 16

Generator 표현에도 List Comprehension과 같이 if에 의한 조건 분기나 for문 중첩도 가능하다.

g_cells = ((row, col) for row in range(0, 3)
           for col in range(0, 2) if col == row)

print(type(g_cells))
# <class 'generator'>

for i in g_cells:
    print(i)
# (0, 0)
# (1, 1)

참고자료

https://note.nkmk.me/python-list-comprehension/

https://qiita.com/supersaiakujin/items/0776d3252c5000ca146e

https://mingrammer.com/introduce-comprehension-of-python/

728x90