Py) 기초 - 제어문(for)

Py) 기초 - 제어문(for)

파이썬 기반 데이터분석을 위하여 for 반복문에 대해 알아본다.


개요

제어문은 영어로 control flow statement라고 하며 크게 조건문과 반복문이 있다. 반복문은 주어진 객체(리스트, 튜플 등) 내부의 요소를 순회(iteration)하며 반복적으로 실행되는 코드이다. 그리고 반복문은 거의 비슷한 코드가 여러번 반복되고 중복된다면 이를 간결하게 만들 수 있다는 장점이 있다. 사용자 정의 함수와 같이 중복되는 코드가 많을 수록 빛을 발한다고 할 수 있겠다. 단, 데이터 핸들링을 위해 불필요하게 반복문을 사용하여 오히려 더 느리고 간결하지 못한 코드를 작성할 수 있으니 유의하자.

생성 및 동작원리

반복문 for는 “for”로 코드를 시작하며 “for” 다음에는 반드시 한 칸 띄어쓴다. 그리고 반복문이 실행되면서 사용될 객체(이하 반복문 객체)를 명시해야 한다. 보통 “i”, “n” 등으로 객체명을 한글자로 지정하는 경우가 많으나 “n_row” 처럼 꼭 한글자가 아니어도 된다. 반복문 객체명 뒤에는 한 칸 띄어쓴 후 “in”을 작성하고 반복문 객체에 하나씩 순차적으로 입력될 값을 명시해준다. 해당 값은 보통 range() 함수로 숫자 뭉치 또는 리스트와 같은 객체를 위치시킨다.

첫 줄 마지막에는 콜론(:)을 써서 마무리하고 반복문이 실행되는 코드는 다음줄 부터 한 수준(4칸 띄어쓰기 또는 1Tab)이상 들여쓰기를 해야한다. 특히 이 부분이 for 반복문에서 빈번하게 일어나는 실수이기 때문에 코드 작성에 유의하도록 한다.

<예시>
1
2
3
4
5
6
for n in range(3):
print(n)

## 0
## 1
## 2

참고로 상기 코드에서 사용하는 반복문 객체 “n”은 다음에 오는 파이썬 코드에 객체 “n”이 있다면 해당 객체에 영향이 갈 수 있다. 왜냐하면 상기 코드가 종료된 이후 다음과 같이 “n”을 출력해보면 2가 출력되기 때문이다.

1
2
n
## 2

그렇기 때문에 되도록이면 for 반복문 객체는 다른 코드에서 사용하지 않는 객체명을 사용하는 것이 좋다.

확장

반복문을 중첩하여 사용할 수 있다. 기존 반복문의 실행코드 영역에 한 수준 더 들여쓰기를 하여 반복문을 또 사용하면 된다. 그런데 여기서 주의할 것이 있다. 반복문을 중첩할 경우 바깥 반복문 객체와 안쪽 반복문 객체명이 같아 이를 공유하게 된다면 의도하지 않은 동작을 야기할 수 있어 주의해야 한다.

<예시>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
for n in range(3):
print("===")
for i in range(3):
print(i)

## ===
## 0
## 1
## 2
## ===
## 0
## 1
## 2
## ===
## 0
## 1
## 2

상기 코드와 같이 for 반복문을 중첩해서 사용하는 경우 반복문 객체를 다르게 해주는 것이 좋다.

실습

가장 기본적인 반복문 형태를 보자. 가장 먼저 소개했던 반복문과 똑같다.

1
2
3
4
5
6
7
8
9
10
11
12
for n in range(3):
print(n)

## 0
## 1
## 2

range(3)
## range(0, 3)

list(range(3))
## [0, 1, 2]

상기 코드를 보면 range(3) 함수의 결과로 0, 1, 2가 나온다는 것을 알 수 있다. 그냥 직접 출력하면 알 수 없는 값이 출력되지만 list() 함수로 range() 함수를 감싼 결과를 보면 쉽게 이해 가능하다. 다시 반복문으로 돌아가 자세히 살펴보자면 range(3) 함수의 결과로 부터 나오는 원소 0, 1, 2를 차례대로 반복문 객체 “n”이 받는다. 그리고 나서 1수준 들여쓰기된 코드가 실행된다. 최종적으로 반복문은 “in” 뒤에 위치한 객체의 원소 개수만큼 반복된다. 즉, 여기서는 range(3) 함수의 실행결과의 원소가 0, 1, 2가 되기 때문에 세 번 반복되는 것이다.

“in” 뒤에는 숫자만 올 수 있는 것은 아니고 다음과 같이 문자를 원소로 하는 리스트가 올 수도 있다.

1
2
3
4
5
for n in ["a", "b"]:
print(n)

## a
## b

가끔 파이썬 사용자 중에서 반복문 객체로 언더바(_)를 사용하는 경우가 있는데 이는 호불호가 갈리기 때문에 본인의 판단에 맡기겠지만 본인은 코드의 가독성이 떨어져 절대 사용하지 않는다.

1
2
3
4
5
6
for _ in [2, 4, 6]: 
print(_)

## 2
## 4
## 6

다음의 반복문은 리스트 객체 “aa”의 원소를 반복문으로 하나씩 꺼내어 확인하는 코드이다.

1
2
3
4
5
6
7
aa = [100, 200, 300]
for n in range(3):
print(aa[n])

## 100
## 200
## 300

다음의 반복문은 리스트 객체 “bb”의 원소를 반복문으로 하나씩 꺼내어 2를 곱한 다음 다시 그 위치에 집어넣는 코드이다. 즉, “bb” 객체의 모든 원소에 2를 곱하는 코드라고 할 수 있겠다.

1
2
3
4
5
6
7
8
bb = [100, 200, 300]
for n in range(3):
bb[n] = bb[n] * 2

bb
## 200
## 400
## 600

다음의 코드는 비어있는 리스트 객체 “cc”에 연산 결과를 하나씩 채워넣는 코드로 이 코드 패턴은 향후 반복문을 활용한 연산 결과의 저장이 필요할 때 요긴하게 활용된다.

1
2
3
4
5
6
7
8
cc = []
for n in range(3):
cc = cc + [n + 100]

cc
## 100
## 101
## 102

앞에서 언급한 2중 for 반복문을 다시 살펴보자.
이해를 돕기 위해 첫 번째 반복문의 첫 코드는 print() 함수를 써서 반복문이 시작할 때를 잘 확인할 수 있도록 했다. 그리고 다음으로 중첩 반복문이 오게 되는데 여기서 range(3) 때문에 3번 반복이 된다. 즉, 바깥 반복문이 한 번 돌 때 내부 반복문은 3번 돌게되기 때문에 총 반복은 9번이 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
for n in range(3):
print("===")
for i in range(3):
print(i)

## ===
## 0
## 1
## 2
## ===
## 0
## 1
## 2
## ===
## 0
## 1
## 2

상기 코드를 보고 이미 눈치챘을 수 있지만 바깥 반복문의 반복문 객체 “n”은 반복문 동작에서 전혀 사용되지 않았다. 이렇게 반복문 객체를 지정하여도 해당 객체를 사용하지 않고 반복만 필요한 경우도 존재한다.

앞에서 언급했던 반복문 객체의 공유와 관련해서 다음의 예제 코드를 보도록 하자. 두 번째 print() 함수는 1수준 들여쓰기된 코드로 바깥 반복문에 직접적으로 속하는 코드이다. 그리고 해당 코드가 실행될 때 출력되는 결과를 보기 편하게 옆에 “@”도 출력되도록 해놓았다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
for L1 in [0, 1, 2]:
for L1 in [100, 200, 300]:
print(L1)

print(L1, "@")

## 100
## 200
## 300
## 300 @
## 100
## 200
## 300
## 300 @
## 100
## 200
## 300
## 300 @

상기 코드를 보면 두 번째 반복문에서 0, 1, 2가 출력되어야 할 것 같지만, 내부 반복문에서 “L1” 반복문 객체를 덮어쓰기 때문에 1, 2, 3이 아니라 하위 반복문에서 덮어쓴 L1값이 출력되어 계속 300이 나오는 것을 볼 수 있다. 이렇게 중첩 반복문에서 각 반복문이 반복문 객체명이 같아 본의아니게 공유되는 경우 의도치 않은 결과를 도출할 수 있기에 사용에 주의해야 한다.

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×