while문

 

- 이번 시간에는 while문에 대해 알아보자.

(while문, 무한루프, n번 반복하기, ~까지 반복하기) 

 

 

 

while문에 대해 설명해주고, 다양한 형태의 예시를 보여줘.

 

Copilot

 

물론입니다! while문은 프로그래밍에서 반복적인 작업을 수행할 때 사용되는 제어문입니다. while문은 특정 조건이 참인 동안 코드 블록을 반복 실행합니다. 조건이 거짓이 되면 반복이 멈춥니다.

 

다양한 형태의 while문 예시를 보여드리겠습니다:

  1. 기본 형태:
    count = 0
    while count < 5:
        print(f"Count: {count}")
        count += 1
    
    AI가 생성한 코드입니다. 신중하게 검토하고 사용하세요. FAQ의 자세한 정보.
    이 코드는 count가 5보다 작을 때까지 반복하여 count 값을 출력합니다.
     
  2. 사용자 입력에 따른 반복:
    user_input = input("계속 반복하시겠습니까? (y/n): ")
    while user_input.lower() == "y":
        print("반복 중...")
        user_input = input("계속 반복하시겠습니까? (y/n): ")
    print("반복 종료")
    
    AI가 생성한 코드입니다. 신중하게 검토하고 사용하세요. FAQ의 자세한 정보.
    사용자가 "y"를 입력하면 계속 반복하고, "n"을 입력하면 반복이 종료됩니다.
     
  3. 무한 루프와 break:
    while True:
        user_input = input("종료하려면 'exit'을 입력하세요: ")
        if user_input.lower() == "exit":
            break
        print("계속 반복 중...")
    print("반복 종료")
    
    AI가 생성한 코드입니다. 신중하게 검토하고 사용하세요. FAQ의 자세한 정보.
    사용자가 "exit"을 입력하면 무한 루프가 종료됩니다.
     
  4. 조건에 따른 반복:
    health = 10
    while health > 0:
        print(f"체력: {health}")
        health -= 2
    print("게임 종료")
    
    AI가 생성한 코드입니다. 신중하게 검토하고 사용하세요. FAQ의 자세한 정보.
    체력이 0보다 큰 동안 반복하여 체력 값을 출력합니다.

while문은 조건이 만족하는 동안 반복해야 할 때 유용하게 사용됩니다. 원하는 조건에 맞게 while문을 활용해보세요! 😊


 
 - 위 예시들 중에서, 3번과 4번을 직접 실행시켜 보기로 하자.
 
 

- 3번 예시의 경우, 그냥 엔터를 치거나 f를 입력했을 때는 while문을 반복하였고, 대문자로 EXIT 를 입력하니 lower() 메소드가 소문자로 바꿔 인식하면서 프로그램이 종료되었음을 알 수 있다.

 

 

- 4번 예시의 경우, 반복 실행하다가 조건을 벗어나는 순간 종료되었다.

 


 

- 이상의 예시들을 살펴보면, 크게 두 가지 형태의 while문으로 분류 가능할 듯하다.

(잠정 결론, 성급한 일반화일 수 있음)

 

형태1. 조건을 먼저 보고 반복하게 한 후에, 탈출 조건을 포함시킨다.

형태2. 무작정 반복하게 한 후에, 탈출 조건을 포함시킨다. (무한루프와 break)

 

- "조건을 보고 시작하는냐, 무한루프로 시작하느냐. 그것이 문제로다.

- 또한, 어떤 형태가 되었든 탈출 조건이 포함되어야 한다.

 

 

조건을 먼저 보는 스타일
무한루프 스타일

 

- 코파일럿이 만들어준 2번 예시의 경우 조건을 먼저 보는 스타일인데, 내가 무한루프 스타일로 바꿔 보았다.

 

 

 

- 보다시피, 결과는 똑같이 나온다.

- 참고로, 불린형 True는 반드시 대문자 T로 시작해야 한다. (실습해 보다가 알았다.)

 

 

 

 

health = 10 
while health > 0: 
    print(f"체력: {health}") 
    health -= 2 
print("게임 종료")

너가 알려준 위 예시의 경우, 'while health > 0' 이 부분을 'while health' 이렇게만 적는 것도 가능하다고 들었어. 

그 이유는 health 가 0이 되는 순간 while문의 조건이 False 가 되기 때문이라고 해. 맞니?

 

Copilot

네, 맞습니다! while health와 while health > 0은 동일한 의미를 가집니다. while health는 health가 0이 아닌 동안 반복하라는 의미이고, while health > 0은 health가 0보다 큰 동안 반복하라는 의미입니다. 따라서 둘 다 체력이 0이 되는 순간 반복이 종료됩니다. 이런 유연성을 활용하여 코드를 작성할 수 있습니다! 😊

 

 

 


하지만, 가독성을 위해서는 'while health > 0' 이 더 좋은 표현 같은데, 굳이 'while health' 와 같이 작성하는 것을 허용하는 특별한 이유가 있니?

 

Copilot

네, 가독성을 고려하여 while health > 0과 같이 명시적으로 조건을 작성하는 것이 좋습니다. 그러나 파이썬은 유연한 문법을 가지고 있어서 while health와 같이 작성해도 동작합니다. 이는 파이썬이 0 이외의 값은 참(True)으로 간주하기 때문입니다. 따라서 while health는 health가 0이 아닌 동안 반복하라는 의미를 가지게 됩니다.

그렇지만 가독성을 높이기 위해 명시적인 조건을 사용하는 것이 좋습니다. 코드를 작성할 때는 다른 사람이 이해하기 쉽도록 명확하게 작성하는 것이 좋은 습관입니다! 😊

 

 

 

 
 

근데, 이런 경우가 생길 수도 있잖아. 예를 들어, 시작값이 10이고 -2만큼 감소시키다가 -10이 되는 순간 while문을 탈출하게 만들고 싶은 거야. 그러면 어떻게 해야해?

 

Copilot
 

 

물론입니다! 시작값이 10이고 -2씩 감소시키다가 -10이 되는 순간 while문을 탈출하려면 다음과 같이 작성할 수 있습니다:

health = 10
while health >= -10:
    print(f"체력: {health}")
    health -= 2
print("게임 종료")
AI가 생성한 코드입니다. 신중하게 검토하고 사용하세요. FAQ의 자세한 정보.

 

위 코드에서 health가 -10 이상인 동안 반복하여 체력 값을 출력하고, health를 2씩 감소시킵니다. 체력이 -10 이하가 되면 반복이 종료되며 “게임 종료” 메시지가 출력됩니다. 이제 프로그램을 실행해보세요! 🚀

 

 

 

 

그렇구나. 그럴 때는 그냥 명시적으로 나타내면 되는구나.

그러면 반대로, 

 

health = -10 

while health: 

    print(f"체력: {health}") 

    health += 2

print("게임 종료") 

 

이렇게 작성하는 것도 가능할까? 

음수의 체력을 증가시켜 나가다가 0이 되는 순간 while문을 탈출하고 싶을 때도 while health 이렇게 작성하는 게 가능한지?

Copilot

네, 맞습니다! while health와 while health > 0은 동일한 의미를 가집니다. 둘 다 체력이 0이 되는 순간 반복이 종료됩니다. 따라서 음수의 체력을 증가시켜 나가다가 0이 되는 경우에도 while health와 같이 작성하는 것이 가능합니다. 이제 프로그램을 실행해보세요! 🚀


 

 

- 프로그램을 실행해 보니 코파일럿의 말이 맞았다.

 

 

- 한편, 내가 지금 보고 있는 위 동영상 강의에서는 while health: 라고만 작성할 경우, 변수 health가 '0 또는 음수'가 될 때 False가 된다고 한다. 하지만 이는 '0 이외의 값은 참(True)으로 간주한다'는 코파일럿의 설명과 충돌한다.

- 그래서 누구의 말이 맞는지 실험해 보기로 했다. (저번에는 코파일럿이 한 번 틀렸었는데...)

 

 

 

- 위와 같이 초기값 10에서 -3씩 감소하게 수정한 후 프로그램을 돌려보니,

10, 7, 4, 1 이렇게 감소해 나가다가, 그대로 0을 지나쳐 마이너스 숫자를 찍어나가기 시작했고, 결국 무한루프에 빠지는 것을 볼 수 있었다. (코파일럿 승!)

 

- 따라서, 체력이 0으로 딱 떨어진다는 보장이 없다거나, 추후 감소분을 변경할 가능성이 조금이라도 있다면 애초에 while health > 0: 이렇게 명시적으로 나타내는 것이 좋을 것이다.

 

- 위 동영상 강의가 초보자도 알아듣기 쉽게 참 설명을 잘해주지만, 아닌 건 아니라고 정확하게 지적해 줘야 한다. 우리가 한걸음 한걸음 나아가면서 정확히 판단하기 위해서는 사실관계를 명확히 해 둘 필요가 있다.

 


 

 

좋아, 이번에는 내가 원하는 내용으로 코딩해보자.

아래 음료 주문 프로그램은 지난 시간에 내가 원하는 내용으로 너가 코딩해준 거야.

 


# 음료 종류
menu = ["아메리카노", "카페라떼", "녹차라떼", "고구마라떼"]

# 메뉴 보여주기
print("다음 음료 중에서 선택하세요:")
for idx, drink in enumerate(menu, start=1):
    print(f"{idx}. {drink}")

# 사용자 입력 받기
selected = int(input("음료 번호를 입력하세요: "))

# 선택한 음료 출력
selected_drink = menu[selected - 1]
print(f"선택한 음료: {selected_drink}")

if selected_drink == "아메리카노" or selected_drink == "카페라떼":
    syrup = int(input("시럽을 몇 번 넣으시겠습니까? (숫자 입력): "))
    print(f"{selected_drink} {syrup}번 시럽을 넣겠습니다.")

print(f"{selected_drink}를 준비하고 있으니 잠시만 기다려 주세요.")

 


위 프로그램을 오늘 배운 while문으로 보강할 생각이야.

보강할 내용은 사용자에게 음료 번호를 입력하라고 하면서, 주문을 마치려면 #버튼을 누르게 하는 거야.
만약, #버튼을 누르지 않으면 계속해서 추가로 음료를 주문 받는 거야. 


예를 들면 아메리카노 시럽1번, 녹차라떼 이렇게 계속 주문 받다가 마지막에 #버튼을 누르면 '주문하신 아메리카노 시럽1번, 녹차라떼 등 총 2잔을 주문받았습니다. 잠시만 기다려주세요.' 라는 문구를 출력해.

 

Copilot

물론, 음료 주문 프로그램을 while 루프로 보강해드리겠습니다. 아래는 보강된 프로그램입니다:

# 음료 종류
menu = ["아메리카노", "카페라떼", "녹차라떼", "고구마라떼"]

# 주문 정보를 저장할 딕셔너리
order = {}

# 메뉴 보여주기
print("다음 음료 중에서 선택하세요:")
for idx, drink in enumerate(menu, start=1):
    print(f"{idx}. {drink}")

# 사용자 입력 받기
while True:
    selected = input("음료 번호를 입력하세요 (주문을 마치려면 '#'을 누르세요): ")
    
    # 주문을 마치는 경우
    if selected == "#":
        break
    
    # 음료 번호가 유효한 경우
    try:
        selected = int(selected)
        if 1 <= selected <= len(menu):
            selected_drink = menu[selected - 1]
            if selected_drink not in order:
                order[selected_drink] = 1
            else:
                order[selected_drink] += 1
        else:
            print("유효한 음료 번호를 입력하세요.")
    except ValueError:
        print("유효한 음료 번호를 입력하세요.")

# 주문 내역 출력
if len(order) > 0:
    total_orders = sum(order.values())
    print(f"주문하신 {', '.join(order.keys())} 등 총 {total_orders}잔을 주문받았습니다. 잠시만 기다려주세요.")
else:
    print("주문이 없습니다. 다음에 또 이용해주세요.")
AI가 생성한 코드입니다. 신중하게 검토하고 사용하세요. FAQ의 자세한 정보.

 

이제 사용자가 음료 번호를 입력하면 주문을 계속 받다가 # 버튼을 누르면 주문 내역을 출력하는 프로그램이 완성되었습니다. 즐거운 프로그래밍 공부 되시길 바랍니다! 😊

 

 

 

 

음... 어렵구나. 아직 배우지 않은 내용이 많아.
일단, 내가 해석은 시도해 볼게.
len(menu) 함수는 메뉴 리스트의 길이인 4를 의미하니? 왠지 len 이 lenth 를 의미할 거 같은데, 맞니?

 

Copilot

네, 맞습니다! len(menu) 함수는 menu 리스트의 길이를 반환합니다. 여기서 menu 리스트는 음료 종류를 담고 있으며, 길이가 4인 것이 맞습니다. 즉, “아메리카노”, “카페라떼”, “녹차라떼”, “고구마라떼” 총 4가지 음료가 있습니다. 이런식으로 파이썬에서 len() 함수를 사용하여 리스트의 요소 개수를 확인할 수 있습니다. 공부하시는데 도움이 되길 바랍니다! 😊

 

 

 

 

그렇다면, 사용자로부터 입력받은 숫자가 1~4 일 경우, 메뉴 리스트의 0~3번 인덱스(메뉴)가 선택될 거고, 그러면

if selected_drink not in order:
    order[selected_drink] = 1

이 부분은, 주문 정보를 저장할 order = {} 이 비어있으면 음료번호와 1을 묶어서 order 에 저장하라는 말이니?

 

Copilot

네, 정확히 맞습니다! 사용자로부터 입력받은 숫자가 1에서 4 사이일 경우, 해당 음료의 인덱스를 계산하여 menu 리스트에서 선택된 음료를 찾습니다. 그리고 이 음료가 order 딕셔너리에 없는 경우, 즉 처음 주문하는 음료인 경우에는 해당 음료를 키로 하고 값을 1로 설정하여 order 딕셔너리에 저장합니다. 이렇게 주문 정보를 저장하면 나중에 주문 내역을 출력할 때 사용됩니다. 고수준의 프로그래밍 이해를 하시는군요! 추가 질문이 있으시면 언제든지 문의해주세요. 😊

 

 

이해만 하면 뭐하니? 내가 직접 작성은 못하고 너가 만들어준 코드를 더듬더듬 읽는 수준인데... ㅎㅎ

 

Copilot

프로그래밍은 처음 시작할 때 어려울 수 있습니다! 하지만 더듬더듬 읽고 이해하는 과정이 중요한 학습 단계입니다. 점점 익숙해지면 직접 코드를 작성하는 데도 능숙해질 것입니다. 열심히 공부하시고, 꾸준한 노력으로 더 나은 프로그래머가 되시길 바랍니다! 😊

 

 

그러면 try 와 except 에 대해서도 설명해줘.

 

Copilot

물론입니다! try와 except는 파이썬에서 예외 처리를 위해 사용되는 키워드입니다.

  • try 블록: 이 부분은 예외가 발생할 수 있는 코드를 감싸는 블록입니다. try 블록 안의 코드가 실행되다가 예외가 발생하면, 프로그램은 except 블록으로 이동합니다.
  • except 블록: 예외가 발생했을 때 실행되는 블록입니다. try 블록 안에서 예외가 발생하면, 해당 예외에 대한 처리를 except 블록에서 수행합니다.

예를 들어, 다음과 같은 상황에서 try와 except를 사용할 수 있습니다:

try:
    # 예외가 발생할 수 있는 코드
    num = int(input("숫자를 입력하세요: "))
    result = 10 / num
    print(f"결과: {result}")
except ZeroDivisionError:
    print("0으로 나눌 수 없습니다.")
except ValueError:
    print("유효한 숫자를 입력하세요.")
AI가 생성한 코드입니다. 신중하게 검토하고 사용하세요. FAQ의 자세한 정보.

 

위 코드에서:

  • 사용자가 숫자를 입력하면 try 블록 안의 코드가 실행됩니다.
  • 만약 사용자가 0을 입력하면 ZeroDivisionError 예외가 발생하고, 이에 해당하는 except ZeroDivisionError 블록이 실행됩니다.
  • 만약 사용자가 숫자가 아닌 문자를 입력하면 ValueError 예외가 발생하고, 이에 해당하는 except ValueError 블록이 실행됩니다.

이렇게 예외 처리를 통해 프로그램이 예외 상황에서도 안정적으로 동작할 수 있도록 할 수 있습니다. 😊

 

 

 


그렇구나, 나중에 배울 내용을 오늘 미리 배운 셈이네.
그러면, 

if len(order) > 0:
    total_orders = sum(order.values())

이 부분에서 order.values() 은 무슨 의미니?

 

Copilot

네, 이해하셨군요! order.values()는 주문 정보를 저장한 딕셔너리인 order의 값들을 가져오는 메서드입니다.

  • order 딕셔너리는 음료 주문 정보를 저장하는 용도로 사용됩니다.
  • order.values()는 딕셔너리의 모든 값들을 가져옵니다. 즉, 주문한 음료의 개수를 나타내는 값들이 리스트 형태로 반환됩니다.
  • sum(order.values())는 이 값들의 합계를 계산합니다. 즉, 주문한 음료의 총 개수를 구하는 것입니다.

따라서 if len(order) > 0: 조건은 주문이 있을 경우에만 주문 내역을 출력하도록 하는 역할을 합니다. 주문이 없는 경우에는 출력하지 않습니다. 😊

 

 

 


', '.join(order.keys()) 

이 부분은 지난번에 배운 join() 메소드로 딕셔너리의 키 값 사이에 콤마를 하나씩 집어넣는 거겠구나.

 

Copilot

네, 정확히 맞습니다! ', '.join(order.keys()) 부분은 딕셔너리의 키 값을 콤마로 구분하여 하나의 문자열로 합치는 역할을 합니다. 딕셔너리의 키들을 콤마로 연결하여 출력하면 주문한 음료의 종류를 보기 좋게 표시할 수 있습니다. 이런 방식으로 프로그래밍에서 문자열을 조작하고 결합하는 기법을 배우시면 좋습니다! 😊

 

 

 

갑자기 장문의 독해를 하게 되니까 좀 당황스러워.

 

Copilot

네, 긴 문장이나 코드를 읽는 것은 처음에는 조금 어려울 수 있습니다. 하지만 조금씩 익숙해지면 더 쉽게 이해하실 수 있을 거예요! 열심히 공부하시고, 점점 더 많은 것을 이해하시길 바랍니다. 😊


 

- 코파일럿의 설명을 듣고 전체적으로 이해가 됐지만, 결론적으로 내가 원했던 프로그램이 아니다.
- 그래도 위 프로그램의 결과가 궁금하니 일단 돌려보기로 하자.

 

 

 

- 첫 번째 실행에서, 아메리카노 2잔과 녹차라떼 1잔을 선택한 후 # 버튼을 누르니 주문 정보를 보여주고 프로그램이 종료되었다.

- 두 번째 실행에서, 메뉴에 없는 숫자와 한글을 입력하니 다시 입력하라는 메시지가 출력되었다.

 

- 하지만, 역시나 내가 원했던 프로그램이 아니었다. (내가 지시를 모호하게 내렸다는 말임)

 

 

- 어떻게 보강해야 할지 고민 끝에 여러가지 방식으로 프롬프트를 작성해 보았다.

 

- 처음에는 아직 공부하지도 않은 클래스 객체가 등장하는 등 코드가 너무 어렵고, 실행 결과도 내가 원했던 방식이 아니어서 프롬프트를 계속 수정해 나갔으나, 첫인상 효과 때문에 코파일럿이 계속해서 비슷한 코드를 작성하는 것을 보고는 새 대화창을 열어 입력해 보았다. (시간부족 및 지면부족 관계로 중간 과정은 생략함)

 

 

 

 

지금부터 파이썬으로 음료 주문 프로그램을 만들 거야. 아래 내용을 코딩해줘.

음료의 종류는 아메리카노, 카페라떼, 녹차라떼, 고구마라떼 등 4가지다.
사용자에게 1~4번까지의 음료 메뉴를 보여준다.

사용자에게 '음료 번호를 입력하세요. (주문을 마치려면 '#' 을 누르세요.) : ' 라는 문구를 출력하여 숫자를 입력받는다.
만약 #이 입력되지 않으면 계속해서 주문을 받는다.
입력받은 숫자가 아메리카노 또는 카페라떼일 경우 시럽을 몇 번 넣을지 물은 후, 음료 이름과 시럽 횟수를 출력해서 보여준다.
입력받은 숫자가 녹차라떼 또는 고구마라떼일 경우, 음료 이름을 출력해서 보여준다.
입력받은 숫자가 유효하지 않거나 다른 문자일 경우, '유효한 음료 번호를 입력하세요' 라는 문구를 출력한 후 계속해서 주문을 받는다.

사용자에게 '음료 번호를 입력하세요. (주문을 마치려면 '#' 을 누르세요.) : ' 라는 문구를 출력했을 때 #을 입력받으면, 지금까지 주문받은 음료의 종류별로 몇 잔인지 열거해서 보여주고, 마지막으로 총 몇 잔인지 보여준다. (예를 들면 '아메리카노 2잔, 카페라떼 1잔, 녹차라떼 2잔 등 총 5잔 주문받았습니다. 잠시만 기다려 주세요.' 라고 출력한다.)

 

Copilot

 

아래는 사용자의 요청에 따라 작성한 파이썬 코드입니다.

# 음료 메뉴
menu = ['아메리카노', '카페라떼', '녹차라떼', '고구마라떼']
# 주문 내역
orders = {name: 0 for name in menu}

while True:
    # 음료 메뉴 출력
    for i, name in enumerate(menu):
        print(f"{i+1}. {name}")
    # 사용자에게 음료 번호 입력 받기
    order = input('음료 번호를 입력하세요. (주문을 마치려면 \'#\' 을 누르세요.) : ')
    # 주문 종료
    if order == '#':
        total = sum(orders.values())
        order_status = ', '.join([f'{name} {count}잔' for name, count in orders.items() if count > 0])
        print(f'{order_status} 등 총 {total}잔 주문받았습니다. 잠시만 기다려 주세요.')
        break
    # 음료 주문
    else:
        try:
            order = int(order) - 1
            if order in [0, 1]:  # 아메리카노 또는 카페라떼
                syrup = int(input('시럽을 몇 번 넣을까요? : '))
                print(f'{menu[order]} {syrup}번 시럽 추가 주문 완료!')
            elif order in [2, 3]:  # 녹차라떼 또는 고구마라떼
                print(f'{menu[order]} 주문 완료!')
            else:
                print('유효한 음료 번호를 입력하세요')
                continue
            orders[menu[order]] += 1
        except ValueError:
            print('유효한 음료 번호를 입력하세요')
AI가 생성한 코드입니다. 신중하게 검토하고 사용하세요. FAQ의 자세한 정보.

 

이 코드는 사용자가 주문을 마치려면 '#'을 입력하도록 요청하며, 주문이 끝나면 주문받은 음료의 종류별로 몇 잔인지, 그리고 총 몇 잔인지 출력합니다. 이 코드를 실행하면 사용자의 요구사항에 따라 음료 주문 프로그램이 작동합니다. 다른 도움이 필요하시면 알려주세요.


 

- 코파일럿이 작성한 위 코드를 조금만 수정해서 프로그램을 돌려보았다.

 

 

 

 

- 아무튼, 미션 성공! 

 

 

 

오늘은, 여기까지...

 

+ Recent posts