으뜸 파이썬 3장 - 제어문

DH Park·2024년 6월 27일
post-thumbnail

https://book.naver.com/bookdb/book_detail.nhn?bid=16268369

으뜸 파이썬과 함께 공부하는 포스트입니다.


우리가 지금까지 작성한 파이썬 프로그램은 먼저 나타나는 코드가 먼저 실행되는 구조이다. 파이썬 뿐만 아니라 대부분의 프로그래밍 언어들이 가지는 일반적인 실행구조이다. 이런 문장을 순차문이라 한다.

실행 결과

위와 같이 최초 상태의 num값이 100이므로 100을 출력 후, 100에 100을 더하여 200, 최종적으로 100을 더하여 300이 된다.

따라서 num값은 순차적으로 100, 200, 300으로 바뀌는 것을 출력문으로 확인해 볼 수 있다. 이렇게 파이썬의 명령은 먼저 나타난 문장이 먼저 실행되는 구조를 가지는데, 이를 순차적 실행구조라고 한다.

이런 코드와 같은 논리적인 구조를 표현한 그림이 자주 사용되는데, 흐름도 라고 한다.


하지만 프로그래밍에서는 순차적 구조만 있는게 아니다. 특정 조건을 만족시킬 때 명령어가 수행되는 경우, 조건에 따라 서로 다른 일을 해야할 경우도 있다. 이렇게 프로그램의 흐름을 제어하는 명령을 제어문이라 한다.

제어문에는 if, if-else같은 조건문, for, while같은 반복문이 잇다. break와 continue 처럼 반복문의 흐름 자체를 변경하는 명령문도 있다.


처음으로, 조건문에 대해 알아보자. 실행문1, 2가 있다고 가정하자. 조건식은 보통 그림으로 표현할 때 다이아몬드로 표현하고, True나 False를 반환한다. 값이 True면 실행문1, False면 실행문 2를 실행하는 구조이다.

이렇게 특정한 조건에 따라 실행 내용이 달라지는 문장 형태가 조건문이다.

조건문 if를 알아보자. if 조건을 쓰고 뒤에 :를 붙인다. 그 후에는 설정한 조건이 참일 때에 실행될 코드들을 입력한다.

이때, 참일 경우 실행되는 코드를 반드시 들여쓰기를 해야 한다. 들여쓰기는 if 조건문에 속한 하위 블록임을 표시하는 것이다. 이제 실습을 해보자.

이 코드는 성인인지 판별할 수 있는 코드이다. 나이가 20살 아래일 때 청소년 할인을 한다는 뜻인데, 할당한 값이 18살이기 때문에 답은 참이다. 그러므로 print()문을 출력해서 아래와 같은 결과가 나온다.

만약 age에 18이 아니고 20보다 큰 수를 할당하면 여기서는 else문을 설정하지 않았으므로 아무것도 출력되지 않을 것이다.

예제를 하나 풀어보자.

게임 사용자의 게임 점수(game_score)가 1000점 이상이면 '당신은 고수입니다.' 를 출력하는 프로그램을 if 문을 이용하여 작성하시오. 이때 다음과 같이 game_score 값을 화면에 출력하여라. (800, 1300점 각각 할당하기)

이 코드는 출력까지 한 상태이다. 그런데 아무것도 나오지 않았다. game_score가 1000 미만이기 때문에 조건문은 False가 되었기 때문이다.

1000 이상인 1300을 할당하니까 값이 True가 되어 print()문이 출력된다.


if-else문을 보기 전에 들여쓰기의 중요성을 살펴보겠다. 조건문은 어떤 조건을 만족하는 경우에 특정 코드를 선택적으로 실행하는 구조를 가지고 있는데 이때 실행될 특정 코드 덩어리를 블록이라고 한다. 새로운 블록은 현재의 들여쓰기보다 더 깊이 들여 써야 한다.

위의 코드는 들여쓰기를 하지 않은 것이다. 이렇게 조건문에서 실행되는 블록을 조건식을 포함하는 if문보다 더 깊이 들여 쓰지 않으면 이런 오류가 출력된다.

오류의 의미는 if문 다음에 들여쓰기 블록이 나와야 하는데 없다는 뜻이다. 들여쓰기는 다른 전통적인 프로그래밍과 다른 파이썬의 특징중 하나이다.

다른 언어가 블록을 열거나 닫는 괄호 표현으로 쓴다면, 파이썬은 그게 아니라 들여쓰기로 블록을 표기하는 것이다.

이러한 표현이 코드를 간결하게 한다.

위의 표를 보면, 각각 if 문장 뒤에 들여쓰기를 한 문장(내부), 들여쓰기를 하지 않은 문장(외부)이 있다.

첫번째 코드는 조건을 만족시킨 경우, 2번째 코드는 조건을 만족시키지 않은 경우이다.

보다시피 들여쓰기를 하지 않은 문장은 둘 다 출력되는데 비해, 들여쓰기를 한 문장은 조건을 만족시킨 경우에만 출력된다. 들여쓰기를 하지 않으면 if문에 영향을 받지 않는다는 뜻이다.

이 경우는 들여쓰기가 잘못된 경우이다. 들여쓰기를 할 때 칸 수도 유의해야 한다는 것을 볼 수 있다.

칸 수는 스페이스바 4칸을 권장한다. 탭키를 사용해도 되지만 권장하는것은 전자이다.


대화형 모드에서 if문

위와같이 if 조건식을 작성 후 블록을 만들면 프롬프트 모양이 >>>에서 ...로 바뀐다. 여기서 들여쓰기를 하면 블록이 계속 만들어지고, 들여쓰기를 하지 않고 엔터키를 누르면 블록을 벗어나 실행된다.

이런 형태는 파이썬의 실행 환경에 따라 다르다.

반면 IDLE에서 파이썬 쉘을 수행 후 if조건문을 실행하면 ...가 나오지 않고 자동으로 들여쓰기를 하게 된다.

이제 부등호가 아닌 배수를 판단해보자.



보다시피 3의 배수인 15를 할당하면 print()문이 출력, 3의 배수가 아닌 16을 할당하면 출력 하지 않게 된다.

또, 3의 배수와 5의 배수를 동시에 출력하고 싶은 경우가 분명 있을 것이다. 이때는 and를 사용하면 된다. 혹은 3의 배수'나' 5의배수 를 출력하고 싶은 경우에는 or을 사용하면 검사를 할 수 있을 것이다.


이제 if-else 조건문을 사용해보자. 이 조건문에서는 조건을 두 개 사용한다.


위 코드를 보면 위의 조건과 아래의 조건은 상반된 결과를 출력하므로 배타적 관계라는 것을 알 수 있다.

hour 값이 12보다 작으면 "오전입니다." 크면 "오후입니다." 를 출력하기 때문이다.

다른 예로는 음수 양수 판별, 짝수 홀수 판별 등 많은 것이 있다.

예제를 하나 풀어보자.

게임 사용자의 게임점수(game_score)를 입력받아서 1000점 이상이면 '고수입니다.' 를 출력하고 1000점 미만이면 '입문자입니다.'를 출력하는 프로그램을 if-else 문을 이용하여 작성하시오. (800, 1300 두개 할당)

실행 결과


복합 조건식

복잡한 조건식을 만들기 이해 비교 연산자와 논리 연산자를 조합하는 경우가 많다. 예를 들면 3의 배수이면서 5의 배수인 값을 알아보기 위해 (n % 3) == 0 and (n % 5) == 0 과 같이 두 조건식을 and로 묶으면 된다.

또는 3의배수 '이거나' 5의배수 인 값을 찾으려면 and 대신 or을 넣어서 출력하면 된다.

조건식에 올 수 있는 연산에는 비교 연산, 부울 연산, 논리 연산이 있다. 세가지 모두 부울 값(True, False)을 반환한다는 공통점이 있다. 실습을 해보자.

실행 결과

두 조건문의 조건식이 모두 참이므로 print() 값이 반환된다. 만약 변수 b값만 홀수로 바꾸면 첫번째 조건식을 만족하지 못하여 두번째 조건문의 print문 만 출력 될 것이다.


if문의 마지막 if-elif-else문을 볼 것이다. 이 조건문은 성적 분류에 자주 쓰인다.

그 전에, 먼저 if문을 여러개 사용하여 성적을 분류해 볼 것이다.

실행 결과

if문만 5개가 있다. 원하는 동작을 수행하기는 한다만 이전에 살펴본 간단한 if문보다 복잡하고 코드의 가독성이 떨어진다.

그리고 계산의 효율성에도 문제가 있다. 만약 학생의 점수가 95라서 A만 출력하면 되는 상황인데, 이 코드는 모든 조건식을 다 검사하는 비효율적 동작을 수행하기 때문에 좋지 않다.

잘못된 조건식이 들어가도 한눈에 오류를 파악하기 힘들다는 점도 단점이다.

이제 if-elif-else문으로 바꾸어 보자.

실행 결과

한눈에 봐도 코드가 간결해진 것을 볼 수 있다.


for 반복문

프로그래밍에서 반복문이라고 하는 것은 특정 작업을 여러번 되풀이해서 수행할 때 사용한다. 이러한 반복문에는 for과 while 두종류인데, for은 반복의 횟수가 미리 정해진 경우, while 문은 반복 횟수는 알지 못하지만 반복 조건이 명확한 경우에 주로 사용한다.

Welcome to Python!을 5회 반복하는 프로그램을 반복문 없이 출력하려면 print()를 5번 쓰면 된다.

실행 결과

이 경우는 5번이라서 간단하게 풀수 있기 때문에 상관이 없지만, 수백, 수천번을 출력하는 경우가 생기면 코드가 매우 비효율적이고 읽기도 힘들어질 것이다. 이런 문제를 해결하기 위해 반복문을 사용하면 효과적이다.

이제 for문을 사용해보자. for문은 for _ in range(): 형식으로 사용한다. 여기서 range는 구간 혹은 범위를 뜻하며, range()함수는 특정한 구간의 정수 열(sequence)을 생성한다. 예를 들어 range(5)는 0에서부터 5가 되기 전까지의 정수인 0,1,2,3,4의 5개 정수열을 차례로 생성한다.

앞서 살펴본 'Welcome to Python!'을 for문으로 반복해보자.

실행 결과

반복 횟수를 바꾸려면 range() 내부의 값만 바꿔주면 된다.

for문은 if문과 마찬가지로 마지막에 콜론(:)을 쓰고, 들여쓰기를 해야 한다. 이러한 for문은 반복 횟수가 정해져 있거나 일정한 크기로 증가하는 숫자를 써야 할 때 주로 사용하는데, 반복문에서 사용되는 변수에는 range()함수에서 생성하는 값이 차례로 할당된다. range(n)이면 0부터 n-1에 해당하는 값까지 1씩 증가하며 할당된다.

실행 결과

위와 같이 for문 안에서 변수 i는 0.1,2,3,4로 바뀌는 것을 출력을 통해 알 수 있다. 이렇게 반복문 내에서 사용되는 변수는 i,j,k,l 같은 알파벳 문자를 할당하는 것이 프로그래밍 언어의 관습이다. 이러한 변수를 C나 Java에서는 루프 제어변수라고 한다.


이제 range() 함수에 대해 더 깊이 알아보자. range() 함수는 단일 정수를 인자로 줄 수도 있지만, range(0,5)와 같이 시작 값과 마지막 값을 지정할 수도 있다.

또, 1씩 증가하지 않고 특정 값만큼 뛰어서 값을 생성할수도 있는데, range(0,5,2)와 같이 마지막에 증가치 값을 넣어주면 된다. range(0,5,2)는 0에서 4까지 범위에서 디폴트 간격 값으로 2씩 더하면서 값을 변경하라는 의미이다.

range()함수와 list() 함수를 같이 활용해보자.

양수 간격 값을 사용할 때에는 시작 값이 종료 조건의 값보다 작아야하고, 음수 간격 값을 생성할 때는 시작이 종료값보다 반드시 커야한다.

반복문을 활용해보자.

먼저 for 문으로는 누적 연산이 가능하다. 1에서 10까지 더한다거나 하는 연산을 쉽게 할 수 있다.

예를 1에서 10까지 덧셈으로 했으니 한번 실행해보지 않을수가 없다.

실행 결과

위 코드는 1에서 10까지 더하면서 누적 과정을 볼 수 있다. format 함수는 나중에 나오므로 설명은 생략하겠다.

이렇게 누적 과정을 보면 어떻게 더해지나 볼 수 있기 때문에 이해하기 편하다.

이번에는 1장에서 일일이 곱하여 구한 팩토리얼을 해볼 것이다.

실행 결과

간결하다. 더한 설명이 필요한가?

덧셈에서 초기값을 0으로 두었지만 곱셈은 0을 곱하면 값도 0으로 나오기 때문에 초기값을 1로 둔다.

그 다음 for문 안에서 곱셈을 사용하는 방식으로 5!를 쉽게 구할 수 있다.


for문과 리스트에 대해 알아보자. for - in 구문은 반복문 키워드 for 와 in 사이에 계속 새롭게 할당할 변수 n을 선언하고 in 뒤에 리스트 자료형을 넣어 리스트를 차례대로 순회하는 실행이 가능하다.

for - in 구문에 리스트를 넣으면 리스트의 항목 개수만큼 코드를 반복하고 변수 n에는 리스트의 객체가 순서대로 하나씩 대입되어 실행된다.

실행 결과

물론 정수 뿐만 아니라 실수도 가능하다.

실행 결과

이 기능과 앞에서 배운 누적 덧셈을 활용하여 리스트 속의 정수 항목 값들의 합을 구해보자.

실행 결과

그리고 앞서 배운 range()는 반복가능 객체를 반환하는데, 반복 가능 객체는 리스트처럼 sum()을 사용할 수 있다.

리스트를 생성하는 것 보다 더 간단히 구할 수 있다.

profile
Offensive Security Consultant

0개의 댓글