본문 바로가기
Python

2024.01.10 (수) while, break, continue, 클래스, 반복문 else

by gosikoca 2024. 1. 10.

while, break, continue, 클래스 각각의 개념을 이해하고 실습문제를 통해 복습을 진행하였습니다.

1. while문

이번에는 for문과 함께 많이 사용되는 구문인 while 문을 살펴보도록 합시다. while문은 조건이 참인 동안에 명령을 반복해서 수행합니다. 반복할 명령은 들여쓰기로 구분되며 조건이 거짓이면 들여쓰기로 구분되어 있는 반복 구문을 탈출합니다.

1.1. while문의 기본 구조

예제를 통해 이해를 돕겠습니다.

변수 a에 1을 저장한 후, 변수 a가 10 미만일 때 변수 a를 출력하고 값을 1 증가시킵니다. 9까지 출력하고 마지막 a+=1이 연산(할당연산)되면 a=10이 되어 조건이 거짓이 되므로 루프를 탈출합니다. 여기서 a+=1을 하지 않으면 무한반복이 되기 때문에 주의해야 합니다.

while문은 조건을 먼저 선언 해주어야 하기 때문에, 비교적 for를 더 많이 사용합니다. 하지만 각각 자주 활용되는 구문들이 있어, 어느 문법이 좋다 할 수 없습니다.

1.2. while로 무한반복 만들기

만약 while 문의 조건이 항상 True이면 무한 반복을 만들 수 있습니다. 이 코드는 ‘무한 반복 중…’ 을 끝없이 출력합니다. 코드 실행을 중지시키려면 colab에 정지버튼을 누르거나 Ctrl(Command)+C를 눌러 수동으로 중지시킬 수 있습니다.

오른쪽 예제를 통해 while을 특징을 잘 보여주고 있으며 무한 반복이 되는 것을 break을 통해 빠져나왔다.

2. 중첩 while문

for문과 동일하게 중첩된 while문으로 구구단을 출력해보도록 하겠습니다.

 

구구단은 2단부터 시작하기에 변수 i를 2로 설정해줍니다. 9단을 수행한 후 종료할 수 있도록 10미만이라는 조건을 설정해주었습니다. i는 구구단의 단을, k는 순차적으로 반복될 곱의 수이며 while문을 하나 더 이용하여 반복될 곱의 수를 1씩 순차적으로 더해주었습니다.

여기서 중요한 것은 종료되는 값입니다. k가 10이 된 상태로 안에 반복문이 종료되기 때문에 3단을 하기 위해서는 다시 k를 1로 초기화 시켜주어야 합니다.

break, continue, pass 비교

1. break 문

break 문은 반복문(while, for)을 실행 중에 중단하고 나오기 위해 사용되는 명령입니다. 주의해야 할 점은 이 break 구문은 바로 위의 반복문(for나 while)만 탈출한다는 것입니다.

기본적인 break 구조에 대해 살펴보도록 하겠습니다.

9까지 출력하지 않았음에도 x == 5인 조건을 만나 break되었음을 알 수 있습니다.

중첩 반복문에서 바로 위에 반복문만 탈출하는 경우도 살펴보도록 하겠습니다. 아래의 경우 각 단의 i X 5까지만 실행이 됩니다.

2. continue, pass

continue의 사전적 의미를 살펴보면 **'계속하다'**라는 뜻이 있습니다. 파이썬에서 continue문은 반복문이 실행하는 코드 블록의 나머지 부분을 실행하지 않고 다음 반복으로 건너가게 흐름을 조정합니다. pass의 사전적 의미는 **'지나치다'**라는 뜻이며, 파이썬에서 pass문은 단순히 실행할 코드가 없다는 것을 의미하며 아무런 동작을 하지 않고 다음 코드를 실행합니다. continue와 pass는 구분해서 사용을 해야 하니 차이점을 잘 정리해 두세요.

반복문 else

1. else

if문 뿐만 아니라 while, for 문에서도 else문을 사용할 수 있습니다. 여기서의 else는 if에서의 else처럼 '그렇지 않으면'이라는 의미 보다는 '그런 다음'이라는 의미가 더 강하기 때문에 than으로 쓰여야 된다는 논의가 있기도 했습니다.

반복문이 break 등에 의해 중단없이 정상적으로 반복이 종료된 후 특정 코드를 실행하게 해야할 때 while~else, for~else를 사용할 수 있습니다.

2. for, else

for문에서의 else는 루프가 정상 종료되었을 때나 처음부터 자료형이 비어있었을 때 실행됩니다. 중간에 break문을 만나면 else 문은 실행하지 않습니다.

바다에 100마리의 물고기가 있고 배에 실을 수 있는 물고기의 수는 5마리라고 가정하도록 하겠습니다.

물고기 5마리를 잡으면 물고기를 더 이상 싣지 못하니 ‘만선입니다. 물고기를 다 잡았습니다.’ 라는 메시지를 띄워줍니다. 이후 break 문을 만나 코드 실행이 종료됩니다.

이번에는 바다에 range(5) 마리의 물고기가 있고 배에 실을 수 있는 물고기의 수는 5마리 입니다. 이때, 바다에는 4마리의 물고기 밖에 없기 때문에 조건에 가기 전에 루프가 종료 됩니다.

그렇기 때문에, 조건문 안에 있는 break문이 실행되지 않고 반복문이 종료됩니다. for문이 종료된 후 else문이 실행됩니다.

3. while, else

for와 마찬가지로 while문에서도 else는 정상 종료되었을 때 실행됩니다. 단, 처음부터 while의 조건문이 False일 경우에도 실행한다는 점을 기억해주세요.

아래의 예시에서는 반복문이 정상 종료됩니다. 따라서 else문이 실행됩니다.

아래와 같은 경우 break문으로 종료가 되기 때문에 else문을 실행시키지 않습니다

실습 프로그램 만들어보기

할일 목록 만들기(To-Do)

Step 1: 할 일 목록 초기화 및 표시 함수

  • 목표: 사용자의 할 일 목록을 관리합니다.
  • 내용:
    • 할 일 목록을 저장할 리스트를 초기화합니다.
    • 할 일 목록을 표시하는 함수를 정의합니다.

Step 2: 할 일 추가 및 삭제 기능

  • 목표: 할 일을 추가하고 삭제하는 기능을 구현합니다.
  • 내용:
    • 할 일을 추가하는 함수를 정의합니다.
    • 할 일을 삭제하는 함수를 정의합니다.

Step 3: 사용자 입력 처리

  • 목표: 사용자 입력에 따라 프로그램이 반응하도록 합니다.
  • 내용:
    • 사용자로부터 입력을 받아 추가, 삭제, 표시 기능을 수행합니다.

클래스

1. 클래스란

클래스는 데이터(멤버 또는 애트리뷰트, 변수)와 기능(메서드, 함수)을 가지고 있는 일종의 설계 도면입니다. 이 설계도면을 통해 생산된 생산품을 인스턴스 객체라 합니다.

여기서 클래스와 인스턴스를 선언하는 형태에 대해 살펴보겠습니다.

클래스 내부에서 선언된 start는 self라는 매개변수, 파라미터를 가지고 있습니다. 여기서 self는 인스턴스 고유의 영역, 인스턴스 자신을 가리킵니다. 여러분이 아규먼트로 전달하지 않아도 자동으로 인스턴스 자신이 아규먼트로 전달됩니다.

이 매개변수의 이름은 self가 아니라 다른 이름이어도 됩니다. 다만 관습적으로 self를 사용하고 있으니 관습에 따라주세요.

위 예제에서 dot을 통해 멤버와 메서드에 접근할 수 있다는 것을 확인했습니다.

위 예제에서 dot을 통해 멤버와 메서드에 접근할 수 있다는 것을 확인했습니다.

Car('Tesla Model X')에서 안에 텍스트는 __init__매직 메서드에 name으로 들어가게 됩니다. __init__ 매직 메서드는 인스턴스가 생성될 때 가장 처음 실행되는 매직 메서드입니다.

클래스 변수와 인스턴스 변수

1. 클래스 변수

클래스 변수는 클래스 바로 하위에 자리하고 있는 변수들 입니다. 이 클래스 변수는 아래의 예시와 같이 클래스 이름, 인스턴스 이름을 통해서 접근할 수 있습니다.

이 클래스 변수는 해당 클래스를 통해 만들어진 모든 인스턴스 객체들이 공유하는 변수 값입니다. 각 인스턴스 객체들 각자가 관리하고 있는 변수는 인스턴스 변수라고 합니다.

위와 같이 작성하면 modely의 max_speed는 500이 됩니다. 모든 변수가 공유하는 변수라고 하였으니 modelx의 값도 바뀌어야 할 것 같지만 modely.max_speed값을 조정하는 것은 modely의 인스턴스 변수의 값을 조정하는 것과 같습니다.

modelx와 modely 인스턴스를 각각 생성하였습니다. 여기에는 self.kinds로 접근하여 append해주는 코드가 있습니다. 인스턴스 영역 내 self.kinds가 없으므로 class 영역에서 해당 변수를 찾아 값을 추가해줍니다.

 

때문에 출력 값을 확인해보면 modelx와 modely도 자신의 메서드를 호출하였을 뿐인데 값이 둘 다 수정된 것을 확인할 수 있습니다. 이는 실제로 두개가 각가의 메모리 영역이 아니라 하나의 메모리 영역을 공유하고 있다는 것을 말해줍니다.

 

Car.speed = 100

이 코드는 클래스에 직접 접근하여 클래스 변수를 수정하였으므로 modelx와 modely의 값이 모두 변경 된 것을 확인할 수 있습니다.

Car에 speed 값을 변경하는 코드는 주석처리하겠습니다.

분명 클래스 변수를 수정한 것 같은데 두 수의 스피드가 공유되고 있지 않습니다. 뒤에 수정된 변수가 반영되어서 500, 250을 출력하는 것이 합당해보입니다.

그렇다면 300은 어떻게 된 것인지 확인해보도록 하겠습니다. 아래 코드를 실행해보세요

 

300은 그대로 클래스 변수에 남겨져 있습니다. 이는 마치 아래 코드와 같습니다.

앞에 있는 kind 리스트는 마치 아래와 같습니다.

앞 클래스에서 kinds배열의 경우에는 add_kinds메서드 안에서 각 인스턴스 객체가 해당 배열의 주소를 참조하고 있어, 그 배열의 주소에 접근하여 조작했기 때문에 클래스 변수를 직접 수정한 것처럼 동작을 하게 된 것입니다. 반면에 speed의 경우에는 change_speed메서드 안에서 인스턴스 변수를 생성하여 값을 가지게 된 것입니다.

2. 인스턴스 변수

인스턴스 변수는 self가 위치한 어디서나 선언이 가능하지만 보통 __init__메서드 안에서 선언됩니다. __init__ 메서드는 다른 프로그래밍 언어에서 생성자(constructor)라 불립니다. 언더바가 2개앞 뒤로 있는 메서드는 매직 메서드, 던더 함수라고 불립니다. 우리는 있는 그대로 __init__ 매직 메서드라고 말하도록 하겠습니다.

이 메서드는 인스턴스 객체를 생성할 때 자동으로 실행됩니다.

인스턴스 객체가 모두 공통으로 공유하는 값이 클래스 변수라면, 인스턴스 변수는 각 인스턴스 객체가 가지고 있는 값으로 인스턴스 내부에서만 사용이 가능합니다.

self가 있는 곳에서 선언된 변수들은 인스턴스의 영역으로 간주되어 dot으로 호출할 수 있습니다. 이 변수는 다른 인스턴스와 메모리 영역을 공유하지 않습니다. 또한 이 값은 아래와 같이 추가 또는 변경이 될 수 있습니다.

클래스 변수 정리

kinds가 공유되지 않도록 구현

speed가 공유되도록 구현