리스트 컴프리헨션이란 새로운 리스트를 만들 때 사용할 수 있는 간단한 표현식으로 리스트와 마찬가지로 대괄호 [
, ]
를 사용하여 작성한다.
만들고자 하는 원소를 표현하는 표현식으로 시작하여 for 루프가 뒤에 따라오는 형식을 가지고 조건문을 추가하여 조건문을 포함한 형식이 될 수도 있다.
[ 표현식 for 원소 in 반복 가능한 객체 ]
[ 표현식 for 원소 in 반복 가능한 객체 if문 ]
TIL - How to Python "pythonically" 에서도 예제를 다룬 적이 있었는데 이번에는 더 간단한 예제로 장점을 살펴보겠다.
1부터 10까지 정수를 가지는 리스트를 만들때 보통 이렇게 할 것이다.
lst = []
for i in range(1, 11):
lst.append(i)
print(lst)
>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
하지만 리스트 컴프리헨션으로 표현하면 다음과 같이 간결하게 작성할 수 있다.
lst = [i for i in range(1, 11)]
print(lst)
>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
여기에 if
조건문을 넣어서 짝수만 리스트에 넣으려면 다음과 같이 작성할 수 있다.
lst = []
for i in range(1, 11):
if i % 2 == 0:
lst.append(i)
print(lst)
>>>
[2, 4, 6, 8, 10]
lst = [i for i in range(1, 11) if i % 2 == 0]
print(lst)
>>>
[2, 4, 6, 8, 10]
import timeit
def for_loop():
num_list = []
for i in range(1000):
num_list.append(i)
def list_comprehension():
num_list = [i for i in range(1000)]
if __name__ == "__main__":
time1 = timeit.Timer("for_loop()", "from __main__ import for_loop")
print("for loop time = ", time1.timeit(number=1000), "milliseconds")
time2 = timeit.Timer("list_comprehension()",
"from __main__ import list_comprehension")
print("list_comprehension time = ",
time2.timeit(number=1000), "milliseconds")
>>>
for loop time = 0.061313478 milliseconds
list_comprehension time = 0.037402701999999996 milliseconds
위의 코드를 보면 for loop
은 0.061 밀리초, list comprehension
은 0.037 밀리초로 절반가까이 빨라졌다.
하지만 리스트 컴프리핸션이 항상 좋은것 만은 아니다. 간단한 컴프리핸션은 더 간단하고 명확할 수 있지만 2중 for loop을 써야 하거나, 복잡한 조건이 들어가야할 경우에는 가독성을 위해서라도 리스트 컴프리핸션을 쓰지 않는게 더 좋을 수도 있다.
Yes:
result = [mapping_expr for value in iterable if filter_expr]
result = [{'key': value} for value in iterable
if a_long_filter_expression(value)]
result = [complicated_transform(x)
for x in iterable if predicate(x)]
descriptive_name = [
transform({'key': key, 'value': value}, color='black')
for key, value in generate_iterable(some_input)
if complicated_condition_is_met(key, value)
]
result = []
for x in range(10):
for y in range(5):
if x * y > 10:
result.append((x, y))
return {x: complicated_transform(x)
for x in long_generator_function(parameter)
if x is not None}
squares_generator = (x**2 for x in range(10))
unique_names = {user.name for user in users if user is not None}
eat(jelly_bean for jelly_bean in jelly_beans
if jelly_bean.color == 'black')
No:
result = [complicated_transform(
x, some_argument=x+1)
for x in iterable if predicate(x)]
result = [(x, y) for x in range(10) for y in range(5) if x * y > 10]
return ((x, y, z)
for x in range(5)
for y in range(5)
if x != y
for z in range(5)
if y != z)
cities = ['Tokyo', 'Shanghai', 'Jakarta', 'Seoul',
'Guangzhou', 'Beijing', 'Karachi', 'Shenzhen', 'Delhi']
without_s = [i for i in cities if i[0:1] == 'S']
print(without_s)
population_of_city = [('Tokyo', 36923000), ('Shanghai', 34000000), ('Jakarta', 30000000), ('Seoul', 25514000), (
'Guangzhou', 25000000), ('Beijing', 24900000), ('Karachi', 24300000), ('Shenzhen', 23300000), ('Delhi', 21753486)]
d = {k: v for k, v in population_of_city}
print(d)
>>>
['Shanghai', 'Seoul', 'Shenzhen']
{'Tokyo': 36923000, 'Shanghai': 34000000, 'Jakarta': 30000000, 'Seoul': 25514000, 'Guangzhou': 25000000, 'Beijing': 24900000, 'Karachi': 24300000, 'Shenzhen': 23300000, 'Delhi': 21753486}
위의 코드는 리스트 컴프리헨션을 사용하여 도시 이름이 S 로 시작하는 리스트를 만들었고, 튜플로 주어진 도시 이름과 인구수를 딕셔너리 컴프리헨션을 사용한 함수를 작성한 결과이다.