본문 바로가기

Python/파이썬 기초

제어문-1

반응형

일상생활에서 조건이나 상황에 따라 처리 결과가 달라지는 경우가 있습니다. 예를 들어, 어떤 시험에서 특정 점수 이상은 합격이고, 미만은 불합격입니다. 대중교통 요금의 경우도 나이 구간에 따라 다릅니다. 실생활과 마찬가지로 컴퓨터 프로그래밍에서도 조건에 따라서 명령을 다르게 수행할 수 있습니다.

 

또한 어떤 일을 할 때 특정한 조건을 만족할 때까지 계속 반복하기도 합니다. 예를 들어, 줄넘기 백 번 하기, 노래 열 번 부르기는 해당 숫자까지 지속해서 반복하는 것입니다. 사람이 어떤 일을 지속해서 반복하는 것은 어렵지만 컴퓨터 프로그램에서 반복하는 것은 어려운 일이 아닙니다. 심지어 어떤 작업을 무한 반복할 수도 있습니다.

 

지금까지 작성한 코드는 앞에서부터 순차적으로 수행됐는데 조건에 따라 코드의 특정 부분만 수행하거나 반복할 수 있습니다. 이처럼 코드의 진행 순서를 바꾸는 구문을 제어문이라고 합니다. 제어문에는 조건을 검사해 분기하는 구문인 조건문과 어떤 구간이나 조건을 만족하는 동안 코드의 일부분을 반복하는 구문인 반복문이 있습니다. 제어문을 이용하면 상황에 따라 다르게 코드를 실행할 수 있어서 프로그램이 지능이 있는 기기처럼 동작하도록 만들 수 있습니다.

 

이번 장에서는 이러한 조건문과 반복문에 대해 알아보겠습니다.

 

 

조건에 따라 분기하는 if 문

조건에 따라 코드를 다르게 실행하려면 if 문을 이용합니다. if 문에서는 지정한 조건에 따라 다르게 분기해 명령을 수행합니다. 따라서 if 문에서는 조건의 만족 여부에 따라서 코드 수행 결과가 달라집니다.

 

단일 조건에 따란 분기(if)

if 문에는 몇 가지 구조가 있는데 단일 조건에 따라서 분기하는 가장 기본적인 if 문의 구조는 다음과 같습니다.

 

if <조건문>:

  <코드 블록>

 

위의 if 문에서 <조건문>을 만족하면(즉, 참이면) 그 아래의 <코드 블록>을 수행하고, 만족하지 않으면(즉, 거짓이면) 수행하지 않습니다. 여기서 <조건문> 다음에는 콜론(:)을 입력합니다. 다음 줄에서 <코드 블록>을 입력할 때 키보드의 탭(Tap)이나 공백(보통 네 칸 정도의 공백을 이용)을 이용해 들여쓰기합니다. <코드 블록>의 코드는 한 줄일 수도 있고 여러 줄일 수도 있습니다.

 

if 문의 <조건문>에는 조건을 판단하기 위해 앞에서 살펴본 비교 연산 및 논리 연산을 이용합니다. 또한 연산과 논리 연산 여러 개를 조합해 사용하기도 합니다.

 

다음은 if 문을 이용해 변수 x의 값이 90보다 크거나 같으면 'Pass'를 출력하는 코드입니다.

 

In : x = 95

     if x>= 90:

        print("Pass")

Out : Pass

 

위의 코드에서 변수 x에는 95가 할당돼 90보다 크거나 같으므로 'Pass'를 출력했습니다. 만약 x가 90보다 작으면 'Fail'을 출력하는 것을 추가하려면 어떻게 해야할까요? 이어지는 내용을 살펴봅시다.

 

단일 조건 및 그 외 조건에 따른 분기(if~else)

앞의 if 문 구조에서는 <조건문>을 만족하면 <코드 블록>을 수행하지만 만족하지 않는 경우는 아무것도 수행하지 않았습니다. 만약 if 문에서 <조건문>의 만족 여부에 따라 코드를 다르게 수행하려면 다음과 같이 'if~else'구조의 조건문을 이용합니다.

 

if <조건문>:

    <코드 블록1>

else :

    <코드 블록2>

 

위의 'if~else' 구조의 조건문에서 <조건문>을 만족하면 <코드 블록1>을 수행하고, 만족하지 않으면 <코드 블록2>를 수행합니다. <조건문> 다음에 콜론(:)을 입력했듯이 else 다음에도 콜론(:)을 입력합니다. 또한 'else:' 다읨의 <코드 블록2>도 들여쓰기를 합니다. 여기서 else는 단독으로 쓸 수 없고 반드시 if와 함께 써야합니다.

 

다음 코드는 'if~else'문의 구조를 이용한 조건문의 예입니다. 변수 x의 데이터가 90보다 크거나 같으면 'Pass'를 출력하고 90보다 작으면 'Fail'을 출력합니다.

 

In : x=75

    if x>= 90:

        print("Pass")

    else:

        print("Fail")

 

Out : Fail

 

위의 코드에서는 변수 x의 값이 75로 90보다 작으므로 'Fail'을 출력했습니다.

 

여러 조건에 따른 분기(if~elif~else)

앞에서 if 구조와 'if~else'구조의 조건문을 살펴봤습니다. 여러 조건에 따른 코드를 각각 다르게 수행하려면 'if~elif~else' 조건문을 이용합니다. 여기서 elif는 필요에 따라 여러 개를 사용할 수도 있습니다.

 

 

if <조건문1>:

    <코드 블록1>

elif <조건문2>::

    <코드 블록2>

          .

          .

          .

elif <조건문n>

    <코드 블록n>

else :

    <코드 블록m>

 

위의 'if~elif~else' 구조의 조건문에서 우선 <조건문1>이 만족하는지 검사하고 만족하면 <코드 블록1>을 수행합니다. 만약 <조건문1>을 만족하지 않는다면 그다음 조건문인 <조건문2>를 검사하고 만족하면 <코드 블록2>를 수행합니다. 만약 <조건문2>도 만족하지 않는다면 그다음 조건문을 검사합니다. 이와 같은 방법으로 마지막 조건문인 <조건문n>을 검사하고 만족하면 <코드 블록n>을 수행합니다. 마지막 조건문까지 만족하지 않으면 'else:' 아래의 <코드 블록m>을 실행합니다. 여기서 'else:' 이후는 생략하고 'if~elif'만 이용할 수도 있습니다.

 

다음은 조건이 여러개인 'if~elif~else' 조건문을 사용한 코드입니다. 변수 x의 값이 90보다 크거나 같으면 'Very good'을 출력하고 80보다 크거나 같고 90보다 작으면 'Good'을 출력하고 80보다 작으면 'Bad'를 출력합니다.

 

In : x=85

    if x>= 90:

        print("Very good")

    elif (x>=80) and (x<90):

        print("Good")

    else:

    print("Bad")

Out : Good

 

위의 코드에서 변수 x에는 85가 할당돼 80보다 크거나 같고 90보다 작은 조건 ('(x>=80) and (x<90)')을 만족하므로 'Good'이 출력됐습니다.

 

앞에서 비교 연산과 논리 연산을 조합해서 만든 조건'(x=>=80) and (x<90)'은 '(80<=x) and (x<90)' 과 같습니다. 파이썬에서는 이와 같은 형태의 경우 '(80>=x>90)'처럼더 직관적으로 표현할 수 있습니다. 다음 예제를 봅시다.

 

In : x=85

    if x>=90:

        print("Very good")

    elif 80<=x<90:

        print("Good")

    else:

        print("Bad")

Out : Good

 

 

중첩 조건에 따른 분기

앞에서 살펴본 조건문의 <코드 블록>에는 또 다른 조건문을 포함할 수 있습니다. 이처럼 조건ㅁ문 안에 또 다른 조건문을 사용한 구조를 중첩 조건문이라고 합니다. 중첩 조건문을 이용하면 다양한 논리로 이뤄진 조건문을 만들 수 있습니다. 다음은 중첩 조건문을 이용한 예입니다.

 

In : x=100

    if x>= 90:

        if x==100:

            print("Perfect")

        else:

            print("Very good")

    elif (x>=80) and (x<90):

        print("Good")

    else:

        print("Bad")

Out : Perfect


위에서 변수 x에는 100이 할당돼 첫 번째 조건 (x=>90)을 만족하고 다시 그 안의 조건문에서 'x==100'을 만족해 'Perfect'가 출력됐습니다.

 

지정된 범위만큼 반복하는 for 문

코드를 작성할 때 지정된 횟수만큼 작업을 반복하거나 지정된 조건을 만족하면 작업을 반복해야 할 때가 있습니다. 이처럼 작업을 반복적으로 수행하는 구문을 반복문이라고 합니다. 파이썬에서는 반복문을 for 문과 while 문을 이용해 구현할 수 있습니다. 우선 for문을 이용한 반복문에 대해 살펴보겠습니다.

 

반복문의 필요성

반복문은 왜 필요한 걸까요? 앞에서부터 순차적으로 코드를 수행하면 안 되는 걸까요? 이를 설명하기 위해 입력한 순서대로 코드가 실행되는 구조로 0부터 5까지 순차적으로 출력하는 코드를 작성해 보겠습니다.

 

In : a=0         # 변수 a를 0으로 초기화

    print(a)      # 변수 a 출력

 

    a=a+1       # 변수 a에 1을 더한 후, 다시 a에 대입

    print(a)      # 변수 a 출력

 

    a=a+1       # 같은 코드 반복

    print(a)      

 

    a=a+1       # 같은 코드 반복

    print(a)      

 

    a=a+1       # 같은 코드 반복

    print(a)      

 

    a=a+1       # 같은 코드 반복

    print(a)      

 

Out : 0       

       1

       2

       3

       4

       5 

위의 코드에서 변수 a에 초깃값 0을 넣고 출력한 후 a에 1을 더한 결과를 다시 a에 대입한 후 결과를 출력하는 코드를 5회 반복했습니다. 위의 예처럼 0부터 5까지 출력할 때는 그나마 코드를 반복해도 문제가 없어보입니다. 하지만 0부터 100까지 출력하는 경우를 생각한다면 위의 코드처럼 똑같은 코드를 반복하는 것은 비효율적입니다. 이때 이용할 수 있는 것이 반복문입니다. 반복문을 이용하면 같은 코드를 반복해서 입력하지 않고 효율적으로 코드를 작성할 수 있습니다.

 

for 문의 구조

for 문은 다음과 같은 구조를 갖습니다. 또한 구조적인 특징으로 인해 'for~in' 문이라고도 합니다.

 

for <반복 변수> in <반복 범위>:

    <코드 블록>

위의 for 문에서 <반복 변수>는 <반복 범위>에 따라 변하면서 <코드 블록>을 실행합니다. 즉, for 문을 시작하면 <반복 범위>의 첫 번째 데이터가 <반복 변수>에 들어가고 <코드 블록>을 실행합니다. 다음은 <반복 범위>의 두 번째 데이터가 <반복 변수>에 들어가고 <코드 블록>을 또 실행합니다. 이런 과정을 <반복 범위>의 마지막까지 반복합니다. <코드 블록>에서는 <반복 변수>를 이요할 수 있습니다. for 문에서도 <반복 범위> 다음에 콜론(:)을 입력하고 그 다음 줄의 <코드 블록>을 입력할 때는 들여쓰기를 합니다.

 

반복 범위 지정

for 문에서 <반복 범위>는 리스트와 range() 함수를 이용해 지정할 수 있습니다. 우선 리스트를 이용하는 방법을 먼저 알아보고, 다음으로 range() 함수를 이용하는 방법을 알아보겠습니다.

 

리스트 이용

리스트는 for 문에서 <반복 범위>에 이용할 수 있습니다. 앞의 예에서 0부터 5까지 순차적으로 출력했던 코드를 for 문을 이용해 작성하겠습니다. 이를 위해 for 문에서<반복 범위>는 출력될 숫자 리스트 ([0,1,2,3,4,5])로 지정하겠습니다. 또한 <반복 변수>는 a로 지정하고 <코드 블록>에서는 print() 함수로 a를 출력하겠습니다. 이를 구현하면 다음과 같은 코드가 됩니다.

 

In : for a in [0,1,2,3,4,5]:

        print(a)

Out : 0

       1

       2

       3

       4

       5

위의 예제에서 for 문이 처음 실행될 때 a에는 리스트의 첫 번째 항목인 0이 대입되고 print(a)가 실행됩니다. 두 번째로 for 문이 실행될 때 a에 리스트의 두 번째 항목인 1이 대입되고 print(a)가 실행됩니다. 이렇게 계속 반복해 실행되다가 a에 리스트의 마지막 항목인 5가 대입되고 print(a)가 실행된 후 반복문은 끝납니다.

 

위의 코드와 출력 결과를 보면 for 문을 이용하지 않고 반복해서 코드를 작성했던 것과 결과는 같은데 작성한 코드는 훨씬 간단해졌습니다. 이처럼 for 문을 이용하면 코드를 반복하지 않고 짧고 간단하게 작성할 수 있습니다.

 

다음은 문자열을 이용해 리스트를 만들고 이를 for 문의 <반복 범위>로 지정한 예입니다. 우선 친구들의 이름을 문자열 리스트로 만들어서 변수 myFriends에 지정합니다. 이것을 for 문의 <반복 범위>로 이요하고 변수 myFriend를 <반복 변수>로 지정한 후 <코드 블록>에서는 print() 함수로 변수 myFriend를 출력하겠습니다.

 

In : myFriends=['James', 'Robert', 'Lisa', 'Mary']     # 리스트를 변수에 할당

    for my Friend in my Friends:

        print(myFriend)

Out : James

       Robert

       Lisa

       Mary

위의 코드에서 for 문이 처음 실행될 때 myFriend에는 리스트 myFriends의 첫 번째 항목('James')이 대입되고 print(myFriend)가 실행됩니다. 이러한 작업을 리스트 myFriends의 마지막 항목('Mary')까지 순차적으로 반복하고 반복문은 끝나게 됩니다.

 

range() 함수 이용for 문의 <반복 범위>를 지정하는 또 다른 방법은 범위를 반환하는 range() 함수를 이용하는 것입니다. 파이썬 내장 함수 range()는 for 문에서 숫자로 <반복 범위>를 지정할 때 많이 이용합니다. range() 함수는 다음과 같이 사용할 수 있습니다.

 

range(start, stop, step)

여기서 start는 범위의 시작 지점, stop은 범위의 끝 지점, step은 증감의 크기입니다. 즉, start부터 시작해서 stop 전까지(즉, stop은 포함되지 않음) step만큼 계속 더해 <반복 범위>를 만듭니다. start와 stop은 양의 점수, 음의 정수, 0 모두 사용할 수 있으며 step은 양의 정수와 음의 정수만 사용할 수있습니다.

 

이제 range() 함수의 예를 살펴보겠습니다.

 

In : print(range(0,10,1))

Out : range(0,10)

위의 코드에서 print()함수를 이용해 range() 함수의 결과를 출력하려고 했으나 실제로 출력이 되지 않았습니다. range() 함수로 만들어진 숫자의 리스트를 출력하려면 다음과 같이 list() 함수를 이용해 리스트 타입으로 변환한 후 출력해야합니다.

 

In : print(list(range(0,10,1)))

Out : [0,1,2,3,4,5,6,7,8,9]

출력 결과에서 range()함수로 생성된 범위는 start부터 stop 전까지입니다. 즉, stop을 포함하지 않습니다.

 

다음은 range() 함수를 이용해 for 문에서 <반복 범위>를 지정한 예입니다.

In : for a in range(0,6,1):

        print(a)

Out : 0

       1

       2

       3

       4

       5

위에서 range(0,6,1)로 생성하는 범위는 0부터 6 전까지 1씩 증가하는 값으로 {0,1,2,3,4,5}가 됩니다. 따라서 for 문의 실행 결과를 보면 0부터 5까지 1씩 증가해서 출력했음을 볼 수 있습니다.

 

앞의 코드에서 step을 1이 아니라 2로 조정해서 <반복 범위>를 바꾸고 싶다면 다음과 같이 코드를 작성하면 됩니다.

 

In : for a in range(0,6,2)"

        print(a)

Out : 0

       2

       4

위에서 range(0,6,2,)는 0부터 6전까지 2씩 증가하는 범위로 {0,2,4}가 됩니다.

 

앞에서 range()함수를 이용할 때 start, stop, step을 모두 지정했습니다. 하지만 step이 1인 경우에는 step을 생략해 다음과 같이 사용할 수 있습니다.

 

range(start,stop)

 

더 나아가 step이 1이고 start가 0인 경우는 start 역시 생략하고 다음과 같이 stop만 지정할 수도 있습니다.

 

range(stop)

다음 코드는 step과 start를 생략한 예입니다. range(0,10,1)에서 step이 1이므로 생략할 수 있어서 range(0,10)으로 지정했고, 다시 start가 0이므로 생략할 수 있어서 stop만 지정해서 range(10)으로 입력했습니다.

 

In : print(list(range(0,10,1)))

     print(list(range(0,10)))

     print(list(range(10))

 

Out :  [0,1,2,3,4,5,6,7,8,9]

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

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

위의 결과에서 range(0,10,1), range(0,10), range(10)이 모두 같은 것을 알 수 있습니다.

 

range() 함수를 이용해 범위를 지정한 다른 예는 다음과 같습니다.

 

In : print(list(range(0,20,5)))           # Line 1

     print(list(range(-10,0,2)))

     print(list(range(3,-10,-3)))

     print(list(range(0,-5,1)))

Out : [0,5,10,15]

       [-10,-8,-6,-4,-2]

       [3,0,-3,-6,-9]

       []

위의 예제에서 첫 번째(Line 1)는 0부터 5씩 증가해 20보다 작은 숫자까지를 출력한 예입니다. 두 번째(Line 2)는 -10에서 2씩 더해 0보다 작은 숫자까지 출력한 예입니다. 세 번째(Line 3)는 3부터 -3씩 증가해서 (혹은 3씩 감소해서) -10보다 큰 숫자까지 출력한 예입니다. 네 번째(Line 4)는 0부터 1씩 증가해서 -5보다 작은 숫자까지 출력한 예이지만, 이런 조건을 만족하는 숫자는 없습니다. 따라서 이 경우는 빈 리스트를 반환합니다.

 

중첩 for문

앞에서 살펴본 if 문의 중첩 조건문처럼 for 문도 중첩 for 문 구조를 이용해 중첩 반복문을 만들 수 있습니다. 중첩 for 문의 구조는 다음과 같습니다.

 

for <반복 변수 1> in <반복 범위 1>:

    for <반복 변수 2> in <반복 범위 2>:

        <코드 블록>

위의 중첩 for 문에서 <반복 변수1>의 첫 번째 데이터가 실행될 때 그 안에 있는 for 문을 만나게 되어 내부 for 문을 실행하고 다시 <반복 변수1>의 두 번째 데이터가 실행될 때 내부 for 문을 수행합니다. 이런 과정을 모두 거쳐서 중첩 for 문을 모두 마치면 코드가 끝납니다. 중첩 for 문에서 내부 for문과 <코드 블록>을 입력할 때도 각각 들여쓰기합니다. 위에서는 for 문 두 개가 중첩된 구조를 만들었지만 더 많은 for문을 중첩할 수도 있습니다.

 

다음은 리스트 변수 x와 y에 각각['x1', 'x2']와 ['y1', 'y2']를 할당하고 for 문 두개를 이용해 각 요소로 이뤄진 (x,y) 의 쌍을 출력하는 코드입니다.

 

In : x_list['x1', 'x2']

     y_list['y1', 'y2']

    

    print("x y")

    for x in x_list:

        for y in y_list:

            print(x,y)

 

Out : x y

       x1 y1

       x1 y2

       x2 y1

       x2 y2

위에서 중첩 for 문을 이용해 <반복 변수1> x의 첫 번째 요소(x1)에 대해 <반복 변수2> y의 첫 번째 요소(y1)와 두 번째 요소(y2)를 출력하고 x의 두 번째 요소(x2)에 대해 <반복변수2> y의 첫 번째 요소(y1)와 두 번째 요소(y2)를 출력했습니다.

 

참고로 print() 함수의 괄호에 출력하고자 하는 것을 콤마(,)로 구분해서 모두 쓰면 각각을공백으로 구분해서 전체를 한 줄에 출력할 수 있습니다. print()함수의 사용법에 관해서는 나중에 자세히 살펴보겠습니다.

 

여러 개의 리스트 다루기

다음은 여러 개의 리스트가 있을 때 for 문을 이용해 리스트의 데이터를 다루는 방법을 살펴보곗습니다. 이를 위해 이름 리스트와 시험점수 리스트를 다음과 같이 만들겠습니다.

 

In : names=['James', 'Robert', 'Lisa', 'Mary']

     scores=[95,96,97,94]

위와 같이 리스트가 두 개 있을 때 이름별로 시험점수를 출력하려면 어떻게 할까요? 리스트가 하나라면 <반복 범위>를 리스트로 지정해 for 문을 이용할 수 있지만 리스트가 두 개이므로 리스트를 <반복 범위>에 이용할 수 없습니다. 이때는 리스트, 튜플, 세트, 딕셔너리의 항목 개수(데이터의 '길이'라고도 함)를 반환하는 len() 함수와 범위를 반환하는 range() 함수를 이용해 for 문의 <반복 범위>를 지정하고 <반복 변수>를 이용해 리스트의 요소를 하나씩 부르면 됩니다.

 

다음은 이것을 구현한 코드입니다.

 

In : for k in range(len(names)):

        print(names[k], scores[k]

Out : James 95

       Robert 96

       Lisa 97

       Mary 94

위의 for 문에서 <반복 범위>를 알기 위해 len() 함수로 리스트의 길이(항목 개수)를 알아냈습니다. 위의 예에서는 len(names)의 항목 개수는 4입니다. 그 결과를 range()함수의 인자로 넣어서 <반복 범위>를 설정했습니다. 따라서 k는 0부터 3까지 1씩 증가하면서 두 리스트(names와 scores)의 항목을 가져와서 출력합니다.

 

길이가 같은 리스트가 여러 개 있는 경우 위와 같은 방법으로 for 문을 이용해도 되지만 같은 길이의 데이터를 하나로 묶어주는 zip() 함수를 이용해 <반복 범위>를 지정하고 데이터별로 <반복 변수>를 지정해 이용할 수도 있습니다.

 

for var1, var2 in zip(list1, list2):

    <코드 블록>

위와 같은 구조로 zip() 함수를 이용해 for 문을 구성하면 <반복 범위>인 zip() 안에 있는 list1과 list2의 항목이 각각 순서대로 동시에 <반복 변수>인 var1, var2에 대입되고 <코드 블록>을 수행합니다.

 

다음은 for 문에서 zip()함수를 사용하는 코드의 예입니다.

 

In : for name, score in zip(names, scores):

        print(name,score)

Out :James 95

       Robert 96

       Lisa 97

       Mary 94

위처럼 for 문에서 길이가 같은 여러 개의 리스트를 처리해야 할 때 zip() 함수를 이용하면 좀 더 알아보기 쉽게 코드를 작성할 수 있습니다.

 

 

                                       출처 : 데이터분석을 위한 파이썬 철저 입문 中

반응형

'Python > 파이썬 기초' 카테고리의 다른 글

입력과 출력-1  (0) 2020.01.21
제어문-2  (0) 2020.01.21
변수와 자료형-4  (0) 2020.01.19
변수와 자료형-3  (0) 2020.01.19
변수와 자료형-2  (0) 2020.01.19