파이썬 기초 강좌 #12 제어문의 개념 & 연산자

22 분 소요

영어로는 cotrol flow 라고 불리는 제어문은 프로그램의 실행 순서를 변경시키거나 또는 조건에따라 실행해야 할 명령문을 제어하는데 사용하는 문장입니다. 파이썬에서 사용되는 제어문은 크게 선택 제어문과 반복 제어문으로 나뉘고, 선택 제어문에는 if 조건문이 있으며 if 조건문을 보조해주는 elif문과 else문이 있습니다. 보통 다른 프로그래밍 언어는 else if 키워드를 사용하지만 파이썬에서는 두 단어를 줄여서 elif 키워드를 사용한다는 점 꼭 기억하시기 바랍니다. 또 다른 제어문으로는 반본 제어문인 for문과 while문이 있으며, 이 반복 제어문을 보조하는 continue와 break 보조 제어문이 있습니다. 파이썬은 다른 프로그래밍 언어가 제공하는 switch 선택문과 do while 반복문을 제공하지 않습니다. 하지만 switch문은 if문으로, do while문은 while문으로 충분히 대체가 가능합니다.

지금 부터 아주 간단한 냉장고 프로그램을 만들면서 제어문이 프로그램안에서 어떻게 사용되는지 보도록 하겠습니다. 지금 부터 만들 프로그램의 기능은 냉장고의 전원이 켜져 있는 동안 1분에 한 번씩 냉장고안의 온도를 측정하고 온도가 임계치인 최고 온도를 초과하면 최고 온도보다 2도 낮은 온도로 조정을 하는 것입니다.

실제 코딩을 시작하기 전에 의사 코드를 작성하는게 좋습니다.

의사코드 (수도코드, pseudocode) 란 프로그램을 설계하는 단계에서 프로그래밍 언어가 아닌 한글이나 영어등과 같이 사람의 언어를 사용하여 자신이 만들고자하는 프로그램의 구조와 알고리즘을 표현하는 것을 말합니다. 쉽게 예를 들면 그림을 그리기 전에 연필로 밑그림을 그리는것과 비슷하다고 보시면 됩니다. 의사코드는 실제 코딩을 하기 전에 프로그래밍 언어를 모르는 사람이나 다른 사람에게 자신의 생각을 쉽게 전달할 수 있게 도와주고, 전체적인 구조나 알고리즘에 문제가 없는지 파악을 하는데 중요한 역할을 합니다.

가장 간단한 의사코드는 이렇게 작성될 것 입니다.

while 냉장고가 켜져있는 동안
  do 1분에 한번씩 온도를 체크하고
  if 온도가 최고 온도를 초과하면
    do 온도를 최고 온도 보다 2 낮게 조정한다.

조금 더 구체적인 의사코드를 작성하면 이런 코드가 완성이 됩니다.

while 냉장고 == ON :
  do 온도 체크
  if 현재 온도 >= 최고 온도:
    print ‘온도를 조정합니다.’
    do 현재 온도 =  최고 온도 - 2
  else:
    print ‘온도가 정상입니다.’
  do 1분간 대기

코드를 보면서 제어문의 기능을 살펴 보도록 하겠습니다.

여기서 while 반복문은 냉장고의 전원이 켜져있는 상태라면 반복하여 아래의 코드 블록이 실행되도록 명령합니다. if 조건문은 현재 온도와 최고 온도를 비교하여 현재 온도가 최고 온도 보다 같거나 높으면 하단의 코드 블록을 실행하고, 그렇지 않으면 else 키워드 아래의 코드 블럭을 실행하게 합니다.

다음은 조금전의 의사코드를 플로우차트로 표현한 것입니다.

플로우차트
플로우차트

플로우차트는 프로그램의 전체 프로세스를 가시화하고 쉽게 이해하고 분석할 수 있게 도와줍니다. 의사코드와 같이 while 반복문의 실행 블럭과, if, else 조건문이 실행되는 블럭이 있는 것을 알 수 있습니다.

의사코드를 작성하고 플로우차트를 그리는 것은 코딩을 시작하기 전에 프로그램을 설계하는 단계에서 아주 중요하면서 기본적인 부분이니 잘 익혀두시기 바랍니다.

조금 전에 작성한 의사코드를 파이썬 코드로 옮기면 다음과 같은 프로그램이 완성이 됩니다.

import time
 
current_temp_list = [5, 3, 4, 6, 5, 4]
is_refrigerator_on = True
max_temp = 5
interval_in_second = 2
current_temp = 0
 
while is_refrigerator_on:
    if len(current_temp_list):
        current_temp = current_temp_list.pop(0)
    else:
        print('프로그램을 종료합니다.')
        break
 
    if current_temp >= max_temp:
        print('현재의 온도는 {}도이며, {}도로 조정하겠습니다.'.format(current_temp, max_temp - 2))
        current_temp = max_temp - 2
    else:
        print('현재의 온도는 {}도이며, 정상입니다.'.format(current_temp))
 
    time.sleep(interval_in_second)

예제 프로그램이므로 온도를 체크하는 인터벌을 1분에서 2초 조정하였고 현재 온도는 미리 리스트로 정의해 놓았습니다. 미리 정해놓은 현재 온도 리스트의 길이가 0이 되면 프로그램이 종료하도록 하였습니다.

코드를 실행하면 다음과 같은 결과가 출력됩니다.

현재의 온도는 5도이며, 3도로 조정하겠습니다.
현재의 온도는 3도이며, 정상입니다.
현재의 온도는 4도이며, 정상입니다.
현재의 온도는 6도이며, 3도로 조정하겠습니다.
현재의 온도는 5도이며, 3도로 조정하겠습니다.
현재의 온도는 4도이며, 정상입니다.
프로그램을 종료합니다.

우리가 만든 냉장고 프로그램이 매 2초 마다 현재 온도를 확인하고 항상 최고 온도인 5도 보다 낮은 온도를 정상적으로 유지하는 것을 확인하였습니다. 물론 실제 프로그램을 만들면 정해진 리스트에서 온도를 입력 받는 것이 아니라 온도계에서 온도 데이터를 받아서 작동을 하고 훨씬 더 복잡한 프로그램이 만들어질 것 입니다. 하지만 아주 복잡한 프로그램도 결국엔 이런 작은 프로그램들이 모여서 만들어진다는 점 꼭 기억하시기 바랍니다.

제어문을 사용하기 위해서는 연산자라는 것을 이해해야 합니다. 영어로는 operater라고 부르는 연산자는 변수에 값을 대입하고, 산수의 사칙연산을 하거나 두개 이상의 값을 비교하기 위해서 사용됩니다. 연산자의 종류에는 산술 연산자, 대입 연산자, 비교 연산자, 논리 연산자 등이 있습니다.

각 연산자를 하나씩 살펴보도록 하겠습니다.

첫 번째로 산술 연산자 (Arithmetic Operators) 를 살펴보겠습니다. 산술 연산자란 산수의 사칙연산과 같은 숫자의 연산을 할 때 사용됩니다. 더하기, 빼기, 곱하기, 나누기는 일반 산수의 사칙 연산과 같습니다.

산술 연산자 (Arithmetic Operators)

연산자연산사용 예
+더하기x + y
-빼기x - y
*곱하기x * y
/나누기x / y
%나머지x % y

간단한 산술 연산자를 실행해보겠습니다.

>>> a = 5
>>> b = 10
>>> a + b  # 덧하기
15
>>> b - a  # 빼기
5
>>> a * b  # 곱하기
50
>>> b / a  # 나누기
2.0

퍼센트 (%) 키워드를 사용하는 연산자는 두 값을 나눈 나머지의 값을 리턴하는 연산자입니다.

>>> 10 % 3
1

연산자의 우선 순위는 산수 계산을 할 때와 같이 곱하기, 나누기가 먼저 계산 되고 더하기, 빼기가 나중에 계산이 됩니다. 더하기와 빼기를 먼저 계산하고 싶을 때는 괄호를 사용하시면 됩니다.

>>> 1 + 1 * 2  # 곱셈, 덧셈 순으로 계산
3
>>> (1 + 1) * 2  # 덧셈, 곱셈 순으로 계산
4

💡 오늘의 팁

수학에서는 0으로 다른 숫자를 나누면 0이 되지만 프로그램에서는 0으로 나누기를 할 수가 없습니다. 0으로 다른 숫자를 나누면 제로 디비전 에러가 발생합니다.

실제로 0으로 숫자를 나눠서 에러를 발생시켜보겠습니다.

>>> 10 / 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

프로그램을 만들다 보면 나누는 수가 어떤 숫자가 될 지 모를 경우가 많습니다. 이런 경우에는 다음과 같이 나누는 값이 0이 아닌지를 확인하는 구문을 꼭 넣어주어야 합니다.

>>> for i in nums:
...     if i != 0:  # 나누는 숫자가 0이 아니면 나누기 실행
...         print(10 / i)
...     else:  # 나누는 숫자가 0이면 나누기를 실행하지 않고, 0을 출력
...         print(0)
...
10.0
5.0
0
3.3333333333333335

다음은 대입 연산자 (Assignment Operators) 입니다. 대입 연산자는 변수에 값을 할당하는 연산자입니다. 이 연산자는 변수 강좌에서도 설명드린대로 산수의 이퀄 사인처럼 양쪽의 값이 같다는 뜻이 아니라 오른쪽의 값을 왼쪽 변수에 할당하는 연산자입니다.

아래 네개의 연산자는 두개의 연산자를 합쳐놓은 것이라고 보시면 되는데요, 두 번째 연산자는 변수에 x 값을 더한 뒤 결과 값을 변수에 할당합니다.

대입 연산자 (Assignment Operators)

연산자사용 예다른 방법
=x = 1x = 1
+=x += 1x = x + 1
-=x -= 1x = x - 1
*=x *= 2x = x * 2
/=x /= 2x = x / 2

코드를 실행해 보겠습니다.

>>> x = 1
>>> x += 1  # x 값에 1을 더한 값을 x에 저장
>>> x
2
>>> x = 2
>>> x -= 1  # x 값에서 1을 뺀 값을 x에 저장
>>> x
1
>>> x = 2
>>> x *= 2  # x 값을 2로 곱한 값을 x에 저장
>>> x
4
>>> x = 4
>>> x /= 2  # x 값을 2로 나눈 값을 x에 저장
>>> x
2.0

다음은 비교 연산자입니다. 비교 연산자는 두 값을 비교하여 TrueFalse를 리턴합니다.

먼저 equal 연산자를 보도록 하겠습니다. equal 연산자는 양쪽의 값이 같으면 True를 양쪽의 값이 다르면 False를 리턴합니다.

비교 연산자 (Comparison Operators)

연산자연산사용 예
==양쪽의 값이 같으면 True를 리턴x == y
!=양쪽의 값이 같지 않으면 True를 리턴x != y
>왼쪽의 값이 더 크면 True를 리턴x > y
<왼쪽의 값이 더 작으면 True를 리턴x < y
>=왼쪽의 값이 오른쪽의 값과 같거나, 더 크면 True를 리턴x >= y
<=왼쪽외 값이 오른쪽의 값과 같거나, 더 작으면 True를 리턴x <= y
>>> print(0 == 0)
True
>>> print(0 == 1)
False
>>> print('one' == 'one')
True
>>> print('one' == 'two')
False

다음은 not equal 연산자입니다. Not equal 연산자는 양쪽의 값이 다르면 True를 양쪽의 값이 같으면 False를 리턴합니다.

>>> print(0 != 0)
False
>>> print(0 != 1)
True
>>> print('one' != 'one')
False
>>> print('one' != 'two')
True

다음은 less than 연산자입니다. Less than 연산자는 왼쪽의 값이 오른쪽의 값 보다 작으면 True를 두 값이 같거나 왼쪽의 값이 크면 False를 리턴합니다.

>>> print(0 < 1)
True
>>> print(0 < 0)
False
>>> print(1 < 0)
False

다음은 greater than 연산자입니다. Greater than 연산자는 왼쪽의 값이 오른쪽의 값 보다 크면 True를 두 값이 같거나 왼쪽의 값이 작으면 False를 리턴합니다.

>>> print(1 > 0)
True
>>> print(0 > 0)
False
>>> print(0 > 1)
False

다음은 less than or equal 연산자입니다. Less than or equal 연산자는 왼쪽의 값이 오른쪽의 값 보다 작거나 두 값이 같으면 True를 왼쪽의 값이 크면 False를 리턴합니다.

>>> print(0 <= 1)
True
>>> print(0 <= 0)
True
>>> print(1 <= 0)
False

다음은 greater than or equal 연산자입니다. Greater than or equal 연산자는 왼쪽의 값이 오른쪽의 값 보다 크거나 두 값이 같으면 True를 왼쪽의 값이 작으면 False를 리턴합니다.

>>> print(1 >= 0)
True
>>> print(0 >= 0)
True
>>> print(0 >= 1)
False

이번에는 논리 연산자에 대해서 알아보도록 하겠습니다. 논리 연산자 역시 비교연산자와 마찬가지로 TrueFalse를 리턴합니다. 다른 프로그래밍 언어와는 달리 파이썬의 논리 연산자는 기호가 아니라 알파벳 키워드를 사용합니다.

먼저 AND 연산자를 보도록 하겠습니다. AND 연산자는 두 개 이상의 비교 결과 값 중, 모든 값이 True일 때 True를 리턴하고 하나라도 False가 있으면 False를 리턴합니다.

실제 코드를 보겠습니다.

>>> print(True and True and True)
True
>>> print(True and True and False)
False
>>> print(False and False and False)
False

위에서 보신 것 처럼 and 연산자는 모든 값이 True일 때만 True를 리턴합니다.

다음은 or 연산자입니다. Or 연산자는 여러개의 값중에 하나만 True가 있어도 True를 리턴합니다.

Or 연산자를 이용해 코드를 실행해보겠습니다.

>>> print(True or True or True)
True
>>> print(True or False or False)
True
>>> print(False or False or False)
False

이번에 살펴볼 not 연산자는 모든 값의 반대의 값을 리턴을 하는 연산자입니다. 즉 True가 값이면 False를 리턴하고 False가 값이면 True를 리턴합니다.

코드를 실행해보겠습니다.

>>> print(not True)
False
>>> print(not False)
True
>>> print(not (True and False))
True
>>> print(not (True or False))
False

다음은 아이덴터티 연산자 입니다. 이 연산자는 비교하는 두 오브젝트가 실제로 같은 메모리 주소를 가진 오브젝트인지를 확인하기 위해서 사용됩니다.

list_1 = [1, 2, 3]
list_2 = [1, 2, 3]

위와 같이 똑같은 멤버를 가진 두 리스트를 이퀄 연산자와 is 연산자로 각각 비교해보면 어떤 값이 나올까요? 실행해보도록 하겠습니다.

>>> list_1 = [1, 2, 3]
>>> list_2 = [1, 2, 3]
>>> print(list_1 == list_2)
True
>>> print(list_1 is list_2)
False

이퀄 연산자는 Trueis 연산자는 False를 리턴했습니다. 왜 그럴까요? 각각의 오브젝트가 가지고 있는 메모리 주소를 출력해보겠습니다.

>>> print(hex(id(list_1)))
0x2136d5e5400
>>> print(hex(id(list_2)))
0x2136d5e3840

이유는 이퀄 연산자는 두 오브젝트의 값만을 비교하여 True를 리턴한 것이고, is 연산자는 두 오브젝트가 가진 메모리 주소를 비교하고 두 오브젝트가 같은 오브젝트가 아니기 때문에 False를 리턴한 것 입니다.

다음은 멤버쉽 (Membership) 연산자입니다. 멤버쉽 연산자는 하나의 값이 어떤 오브젝트안에 속해 있는지 확인하기 위해 사용됩니다. 멤버쉽 연산자는 주로 한 문자열안에 어떤 문자열이 포함되있는지 확인하거나, 리스트가 어떤 값을 가지고 있는지 확인할 때 많이 사용됩니다. 딕셔너리의 멤버를 확인할 때는 value를 찾는 것이 아니라 key를 찾는다는 점 꼭 기억하시기 바랍니다.

>>> print('two' in 'one two three')
True
>>> print(2 in [1, 2, 3])
True
>>> print('key_1' in {'key_1': 'value_1', 'key_2': 'value_2'})
True
>>> print(4 not in [1, 2, 3])
True
>>> print('four' not in 'one two three')
True
>>> print('key_3' not in {'key_1': 'value_1', 'key_2': 'value_2'})
True

이번 강좌에서는 제어문의 역할과 연산자에 대해서 알아보았습니다. 다음 강좌에서는 각각의 제어문의 구체적인 사용 방법을 공부해 보도록 하겠습니다.