이 글의 작성자는 C/C++ 프로그래밍을 하던 사람이다. 이 글은 Python을 복습하며 작성하는 글이니, 부족한 부분이 있으면 얼마든지 피드백을 주시기 바란다.

 

range()

리스트에 자꾸 이상한 문자열을 끼워넣어서 수학마스터 김씨에게 한소리 들은 최씨는 “내가 직접 리스트를 만들면 안되겠다”라는 생각을 했다. Python의 기능을 이용하여 리스트 항목을 생성하면 내가 실수할 일이 없어지지 않을까? 라는 생각을 하며 기능을 찾아보기 시작했다.

우선은 리스트에 [0,1,2,3,4,5...]순으로 1씩 증가하는 숫자가 들어있는 리스트를 만들어보고자 했다. 그리고 최씨는 range()라는 것을 찾아냈다.

range는 순회 가능한 객체다. 리스트나 튜플처럼, for 문을 이용하여 순회할 수 있는 객체다. 그러면 어떻게 생겼는지 한번 살펴보자. 한번 range 객체를 생성하고 이 객체를 출력하는 동작을 인터프리터에서 간단하게 수행해보자.

>>> a = range(4)
>>> print(a)
<class 'range'>

정수나 리스트를 출력할 땐 객체에 들어있는 값들이 보였는데, range 객체는 그런게 보이지 않는다. range에는 무엇이 담겨있는 것일까? 순회 가능한 객체라고 했으니 한 번 for문을 이용하여 순회해보자.

>>> for i in a:
    print(i)
0
1
2
3

0부터 3까지 출력되었다.

 

한마디로, range는 연속된 숫자의 흐름을 표현하는 객체이다. 그러면 range를 생성하는 방법에 대해서 알아보자.

range([start,] stop [,step])

대괄호 안에 들어있는 요소는 생략이 가능하다는 것을 미리 알려둔다.

range는 range 객체를 생성하는 함수를 의미한다.
start는 생략이 가능한 요소로, 어디서부터 시작할지를 정한다. start가 2라면, range 객체의 첫 번째 수는 2가 된다. 만약 start를 생략했다면, start는 자동으로 0이 된다.
stop은 반드시 들어가야 하는 요소로, 어디까지 출력할 지를 정한다. 문자열이나 리스트의 일부를 가져올 때 사용했던 기능을 생각하면 된다. stop이 9라면, range는 9부터는 포함이 되지 않는다.
step은 생략이 가능한 요소로, 숫자 간의 간격이 얼마나 되는지를 정한다. step이 2라면, 맨 첫번째 숫자가 1이었으면 그 다음 숫자는 3, 5, 7… 순으로 들어가게 된다.

그러면 다음과 같이 생성된 range 객체가 어떤 숫자를 담고 있는지 확인해보자.

a = range(5)         # [0,1,2,3,4]
b = range(2,10)      # [2,3,4,5,6,7,8,9]
c = range(3,9,2)     # [3,5,7]

 

이렇게 생성된 range 객체는 숫자들을 담고 있지만, 리스트의 형태는 아니다. range 객체를 리스트 형태로 바꾸려면 어떻게 해야할까?

append()를 사용하는 방법이 있다. 비어있는 리스트를 하나 생성하고, 거기다가 range의 항목을 하나씩 집어넣으면 된다.

l = []
for i in range(5):
    l.append(i)

이러면 l에는 [0,1,2,3,4]가 담기게 된다. 최씨가 일일이 l = [0,1,2,3,4]를 치지 않아도 되고, 만약 집어넣어야 할 수가 변경되어도 range에 있는 괄호 안의 숫자만 바꿔주면 되므로 편리하게 리스트의 항목을 생성할 수 있게 된다.

하지만 이보다 더 간편한 방법이 있다.

l = list(range(5))

여기서 리스트와 튜플을 변환하는 것을 본 적이 있다. list() 안에 순회 가능한 객체가 들어간다면, 리스트는 알아서 주어진 객체를 순회하면서 리스트의 형태로 만들어지게 된다. 리스트도 순회 가능하고, 튜플도 순회 가능하고, range도 순회 가능하다. 따라서 append()를 이용해서 하나하나 집어넣기 보다는 간단하게 list()로 만들어 주는 것이 깔끔하다.

 

리스트 컴프리헨션(comprehension)

이번엔 조금 더 복잡해 보일 수 있으나, 강력한 도구인 컴프리헨션(comprehension)을 알아보자.

comprehension의 뜻은 영어 사전을 찾아보면 독해, 이해력이라고 나온다. 무슨 기능을 하길래 이런 뜻을 가지고 있을까? 위에서 만들었던 range(5) 리스트를 리스트 컴프리헨션으로 만들면 다음과 같이 만들 수 있다.

l = [v for v in range(5)]

그리고 l을 출력해보면 [0,1,2,3,4]가 들어있는 것을 확인할 수 있을것이다.

잘 살펴보면 지난 번에 배웠던 for문이 리스트 안에 들어있는 것처럼 보인다. 마치 for문을 순회하면서 리스트를 만드는 것 처럼 보인다.
그러면 리스트 컴프리헨션을 일반적으로 어떻게 표현하는지 보자.

[expression for item in iterable]

expression은 리스트에 들어갈 값이다. itemiterable에 들어있는 값이다.

즉, iterable을 순회하며, item의 값을 expression을 통하여 적절하게 편집하여 리스트에 집어넣는다고 보면 된다.

[0,2,4,6,8]을 컴프리헨션으로 만든다면 다음과 같이 할 수 있을 것이다.

[v*2 for v in range(5)]

원래 있던 리스트 l의 원소들을 1씩 더한 리스트는 이렇게 만들 수 있을 것이다.

[v+1 for v in l]

그냥 숫자 0만 들어있는 리스트를 만들 수도 있다.

[0 for v in range(5)]

expressionitem이 위의 예시처럼 아무런 연관이 없어도 쓸 수 있다.

이 예시는 [0] * 5 로도 생성할 수 있다.

 

이걸로 끝이 아니다. 무려 조건부로 추가할 수도 있다!

[expression for item in iterable if condition]

이렇게 될 경우, 각각의 item에 대해 condition이 True가 될 경우에만 expression의 값을 리스트에 추가하게 된다.

0부터 9까지의 숫자 중, 홀수만 집어넣고자 하면 이렇게 할 수 있을 것이다.

[v for v in range(10) if v%2 == 1]

아니면 최씨가 실수로 리스트에 문자열을 추가했다고 하더라도, 이런 식으로 정수인 데이터만 들어 있는 리스트를 새로 만들수도 있겠다.

[v for v in numbers if type(v) is int]

 

컴프리헨션은 간결하고도 강력한 리스트 생성 기능이다. 자연스럽게 사용할 수 있도록 많이 연습해보자.

 

Categories:

Updated:

Comments