리스트 컴프리헨션(list comprehension)의 이해

리스트 컴프리헨션(list comprehension)에 대해서 알아보겠다. 리스트를 생성하는데 아주 편리하고 정말 많이 사용하는 파이썬 문법입니다. 한번 정리해두고 두고 써먹자!



 

리스트 컴프리헨션

리스트 컴프리헨션. 영어라 말이 어려운 것 처럼 보일뿐이지 실상 내용이 어려운 것은 아니다. list 를 생성하는데 좀 더 편리하게 생성하는 하나의 문법일 뿐이다. 긴말은 생략하고 ‘하하’ 라는 문자열이 100개가 들어있는 리스트를 생성해보자.

 

haha = []
for count in range(100):
    haha.append('하하')

이렇게 하면 리스트 안에 ‘하하’ 라는 문자열이 생성되게 된다. 리스트 컴프리헨션을 활용해 코드를 좀 더 편리하게 써보자.

 

for 문

단일 for문

haha = ['하하' for count in range(5)]

한줄로 쪼끔 우아해졌나? 언뜻 봐도 위에 표현보다는 좀 더 편리해보인다. 리스트를 선언할 때 리스트 안에 곧바로 자료를 for문과 함께 넣는 형태이다. for 문을 한번만 써봤는데 이번에는 두개를 써보자

다중 for문

list1 =['가', '나', '다', '라', '미']
list2 =['a', 'b', 'c', 'd', 'e']

haha = [str(hangul)+str(alphabet) for hangul in list1 for alphabet in list2]

# 결과
# ['가a', '가b', '가c', '가d', '가e', '나a', '나b', '나c', '나d', '나e', '다a', '다b', '다c', '다d', '다e', '라a', '라b', '라c', '라d', '라e', '미a', '미b', '미c', '미d', '미e']

haha = []
for hangul in list1:
    for alphabet in list2:
        haha.append(str(hangul) + str(alphabet))

# 결과 : 위와 동일
# ['가a', '가b', '가c', '가d', '가e', '나a', '나b', '나c', '나d', '나e', '다a', '다b', '다c', '다d', '다e', '라a', '라b', '라c', '라d', '라e', '미a', '미b', '미c', '미d', '미e']

for 문을 두개 넣으면 복잡해진다. 유심히 잘 보고 하나씩 이해를 해보는 것이 좋다. 위와 아래는 동일한 코드 내용인데, 둘은 데이터 처리 속도상에서 별 차이가 없다. 개인적으로 for 문이 2개 이상 들어가는 것은 아래 형식으로 사용하는게 좋다고 생각한다. 문장은 길어보이지만 실수를 줄이고 가독성이 좋다.

if 문

단일 if문

for문과 if 문을 섞어서 원하는 데이터만을 추려낼 수 있다.

onetoten = [num for num in range(1,11)]
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

multiples_of_3 = [number for number in onetoten if number % 3 == 0]
# [3, 6, 9]

일단 1부터 10까지 숫자를 담고 있는 리스트를 생성한다. 이 중에 3의 배수만을 추려낸 숫자만을 담은 리스트를 따로 생성한다고 할 때 위와같이 만들 수 있겠다. num % 3 == 0 의 의미는 3으로 나누었을 때 나머지가 0인 숫자를 말한다. (%는 나머지를 구하는 연산자)

다중 if문

multiples_3and5 = [number for number in onetoten if number % 3 == 0 or number % 5 == 0]

# [3, 5, 6, 9, 10]

commonmultiof2and3  = [number for number in onetoten if number % 2 == 0 if number % 3 == 0]

# [6]

첫번째는 2 또는 3의 배수일 숫자만 골라낸 것이고, 두번째는 2의 배수이면서 3의 배수인것. (= 공배수) 을 구하는 것이다.
참고로 두번째 코드는 요렇게 같이 해도 결과는 동일하다

commonmultiof2and3  = [number for number in onetoten if number % 2 == 0 and number % 3 == 0]

openpyxl 에서 사용례

openpyxl 에서는 많은 셀들을 다룬다. 예를 들어 ‘A’ 열의 모든 셀들을 리스트로 가져온다던지, 혹은 첫번째 행의 모든 셀들을 가져온다던지. 그렇다.
A열의 모든 셀들 가져오려면 다음과 같다.

rowA = [cell.value for cell in ws['A']]

그냥 cell.value 라고 한것은 셀의 값을 가져오기 위함이다. cell.value 라고 하지 않고 cell 이라고만 하면 셀의 값을 가져오는게 아니라 셀 객체 그 자체를 가져오게 된다.

참고로 openpyxl 에 대한 전반적인 이해를 원한다면 openpyxl 사용법 기초 를 참고하자

generator 생성

많은 데이터를 처리하다보면 메모리를 절약하기 위해 제네레이터를 사용한다. 입문자라면 제네레이터가 무엇인지 몰라도 별 관계없다.

제네레이터 생성은 리스트 컴프리헨션과 비슷하다 괄고를 [] 대신 () 을 사용해주면 된다.

genhaha = ('하하' for _ in range(5))

참고로 소괄호 () 가 튜플(tuple) 의 형태와 같다고 해서 이것을 튜플 컴프리헨션이라고 착각하는 사람이 있는데 이것은 튜플 컴프리헨션이 아니다. 제네레이터를 생성하는 방법이니 오해가 없기 바란다.

Leave a Comment